diff --git a/doc/draft/draft-ietf-ipngwg-2292bis-00.txt b/doc/draft/draft-ietf-ipngwg-2292bis-00.txt new file mode 100644 index 0000000000..c25ce740ed --- /dev/null +++ b/doc/draft/draft-ietf-ipngwg-2292bis-00.txt @@ -0,0 +1,3531 @@ + + + + + + +INTERNET-DRAFT W. Richard Stevens (Consultant) +Expires: December 24, 1999 Matt Thomas (Consultant) +Obsoletes RFC 2292 Erik Nordmark (Sun) + June 24, 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-00.txt [Page 1] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 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 December 24, 1999. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 2] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + +Table of Contents + + 1. Introduction .................................................... 6 + + 2. Common Structures and Definitions ............................... 7 + 2.1. The ip6_hdr Structure ...................................... 7 + 2.1.1. IPv6 Next Header Values ............................. 8 + 2.1.2. IPv6 Extension Headers .............................. 8 + 2.2. The icmp6_hdr Structure .................................... 10 + 2.2.1. ICMPv6 Type and Code Values ......................... 11 + 2.2.2. ICMPv6 Neighbor Discovery Type and Code Values ...... 12 + 2.3. Address Testing Macros ..................................... 14 + 2.4. Protocols File ............................................. 15 + + 3. IPv6 Raw Sockets ................................................ 15 + 3.1. Checksums .................................................. 17 + 3.2. ICMPv6 Type Filtering ...................................... 17 + + 4. Access to IPv6 and Extension Headers ............................ 20 + 4.1. TCP Implications ........................................... 21 + 4.2. UDP and Raw Socket Implications ............................ 22 + + 5. Packet Information .............................................. 23 + 5.1. Specifying/Receiving the Interface ......................... 24 + 5.2. Specifying/Receiving Source/Destination Address ............ 25 + 5.3. Specifying/Receiving the Hop Limit ......................... 25 + 5.4. Specifying the Next Hop Address ............................ 26 + 5.5. Additional Errors with sendmsg() and setsockopt() .......... 26 + + 6. Routing Header Option ........................................... 27 + 6.1. inet6_rth_space ............................................ 28 + 6.2. inet6_rth_init ............................................. 29 + 6.3. inet6_rth_add .............................................. 29 + 6.4. inet6_rth_reverse .......................................... 29 + 6.5. inet6_rth_segments ......................................... 30 + 6.6. inet6_rth_getaddr .......................................... 30 + + 7. Hop-By-Hop Options .............................................. 30 + 7.1. Receiving Hop-by-Hop Options ............................... 31 + 7.2. Sending Hop-by-Hop Options ................................. 31 + + 8. Destination Options ............................................. 32 + 8.1. Receiving Destination Options .............................. 32 + 8.2. Sending Destination Options ................................ 33 + + 9. Hop-by-Hop and Destination Options Processing ................... 33 + 9.1. inet6_opt_init ............................................. 34 + 9.2. inet6_opt_append ........................................... 34 + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 3] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + 9.3. inet6_opt_finish ........................................... 35 + 9.4. inet6_opt_set_val .......................................... 35 + 9.5. inet6_opt_next ............................................. 35 + 9.6. inet6_opt_find ............................................. 36 + 9.7. inet6_opt_get_val .......................................... 36 + + 10. Ordering of Ancillary Data and IPv6 Extension Headers ........... 37 + + 11. IPv6-Specific Options with IPv4-Mapped IPv6 Addresses ........... 37 + + 12. Extended interfaces for rresvport, rcmd and rexec ............... 38 + 12.1. rresvport_af .............................................. 38 + 12.2. rcmd_af ................................................... 38 + 12.3. rexec_af .................................................. 39 + + 13. Future Items .................................................... 39 + 13.1. Flow Labels ............................................... 39 + 13.2. Path MTU Discovery and UDP ................................ 39 + 13.3. Neighbor Reachability and UDP ............................. 39 + + 14. Summary of New Definitions ...................................... 39 + + 15. Security Considerations ......................................... 42 + + 16. Compatibility with RFC 2292 ..................................... 43 + + 17. Change History .................................................. 43 + + 18. TODO and Open Issues ............................................ 44 + + 19. References ...................................................... 45 + + 20. Acknowledgments ................................................. 46 + + 21. Authors' Addresses .............................................. 46 + + 22. Appendix A: Ancillary Data ...................................... 46 + 22.1. The msghdr Structure ...................................... 47 + 22.2. The cmsghdr Structure ..................................... 48 + 22.3. Ancillary Data Object Macros .............................. 49 + 22.3.1. CMSG_FIRSTHDR ...................................... 50 + 22.3.2. CMSG_NXTHDR ........................................ 51 + 22.3.3. CMSG_DATA .......................................... 52 + 22.3.4. CMSG_SPACE ......................................... 52 + 22.3.5. CMSG_LEN ........................................... 53 + + 23. Appendix B: Examples using the inet6_rth_XXX() functions ........ 53 + 23.1. Sending a Routing Header .................................. 53 + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 4] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + 23.2. Receiving Routing Headers ................................. 58 + + 24. Appendix C: Examples using the inet6_opt_XXX() functions ........ 60 + 24.1. Building options .......................................... 60 + 24.2. Parsing received options .................................. 62 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 5] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 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 headers. This allows programs such as Ping + and Traceroute, for example, to compile with minimal effort on many + hosts that support the sockets API. With IPv6, however, there is no + common source code base that implementors are starting from, and the + possibility for divergence at this level between different + implementations is high. To avoid a complete lack of portability + amongst applications that use raw IPv6 sockets, some standardization + is necessary. + + 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-00.txt [Page 6] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 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 headers are required, along with common + constant definitions for the structure members. + + Two new headers are defined: and . + + When an include file is specified, that include file is allowed to + include other files that do the actual declaration or definition. + + +2.1. The ip6_hdr Structure + + The following structure is defined as a result of including + . Note that this is a new header. + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 7] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + + struct ip6_hdr { + union { + struct ip6_hdrctl { + uint32_t ip6_un1_flow; /* 8 bits traffic class, 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. + 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 + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 8] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + 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 */ + struct in6_addr ip6r0_addr[1]; /* up to 127 addresses */ + }; + + /* Fragment header */ + struct ip6_frag { + uint8_t ip6f_nxt; /* next header */ + uint8_t ip6f_reserved; /* reserved field */ + uint16_t ip6f_offlg; /* offset, reserved, and flag */ + uint32_t ip6f_ident; /* identification */ + }; + + #if BYTE_ORDER == BIG_ENDIAN + #define IP6F_OFF_MASK 0xfff8 /* mask out offset from _offlg */ + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 9] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + #define IP6F_RESERVED_MASK 0x0006 /* reserved bits in ip6f_offlg */ + #define IP6F_MORE_FRAG 0x0001 /* more-fragments flag */ + #else /* BYTE_ORDER == LITTLE_ENDIAN */ + #define IP6F_OFF_MASK 0xf8ff /* mask out offset from _offlg */ + #define IP6F_RESERVED_MASK 0x0600 /* reserved bits in ip6f_offlg */ + #define IP6F_MORE_FRAG 0x0100 /* more-fragments flag */ + #endif + + Defined constants for fields larger than 1 byte depend on the byte + ordering that is used. This API assumes that the fields in the + protocol headers are left in the network byte order, which is big- + endian for the Internet protocols. If not, then either these + constants or the fields being tested must be converted at run-time, + using something like htons() or htonl(). + + (Note: We show an implementation that supports both big-endian and + little-endian byte ordering, assuming a hypothetical compile-time #if + test to determine the byte ordering. The constant that we show, + BYTE_ORDER, with values of BIG_ENDIAN and LITTLE_ENDIAN, are for + example purposes only. If an implementation runs on only one type of + hardware it need only define the set of constants for that hardware's + byte ordering.) + + +2.2. The icmp6_hdr Structure + + The ICMPv6 header is needed by numerous IPv6 applications including + Ping, Traceroute, router discovery daemons, and neighbor discovery + daemons. The following structure is defined as a result of including + . Note that this is a new header. + + + + + + + + + + + + + + + + + + + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 10] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + + 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 */ + #define ICMP6_DST_UNREACH_ADMIN 1 /* communication with */ + /* destination */ + /* admin. prohibited */ + #define ICMP6_DST_UNREACH_NOTNEIGHBOR 2 /* not a neighbor */ + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 11] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + #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 + #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 + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 12] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + #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 + #define nd_rd_reserved nd_rd_hdr.icmp6_data32[0] + + struct nd_opt_hdr { /* Neighbor discovery option header */ + uint8_t nd_opt_type; + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 13] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + 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.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 + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 14] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + including . + + int IN6_ARE_ADDR_EQUAL(const struct in6_addr *, + const struct in6_addr *); + + + +2.4. Protocols File + + Many hosts provide the file /etc/protocols that contains the names of + the various IP protocols and their protocol number (e.g., the value + of the protocol field in the IPv4 header for that protocol, such as 1 + for ICMP). Some programs then call the function getprotobyname() to + obtain the protocol value that is then specified as the third + argument to the socket() function. For example, the Ping program + contains code of the form + + struct protoent *proto; + + proto = getprotobyname("icmp"); + + s = socket(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 + + + +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 + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 15] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + 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 later in this document. Should an + application need access to the complete IPv6 packet, some other + technique, such as the datalink interfaces BPF or DLPI, must be used. + + All fields in the IPv6 header that an application might want to + change (i.e., everything other than the version number) can be + modified using ancillary data and/or socket options by the + application for output. All fields in a received IPv6 header (other + than the version number and Next Header fields) and all extension + headers are also made available to the application as ancillary data + on input. Hence there is no need for a socket option similar to the + IPv4 IP_HDRINCL socket option 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 + is normally 255. We note that this value has no special meaning to + an IPv6 raw socket (and the IANA currently reserves the value of 255 + when used as a next-header field). (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 + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 16] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + IP_HDRINCL socket option was added.) + + +3.1. Checksums + + The kernel will calculate and insert the ICMPv6 checksum for ICMPv6 + raw sockets, since this checksum is mandatory. + + For other raw IPv6 sockets (that is, for raw IPv6 sockets created + with a third argument other than IPPROTO_ICMPV6), the application + must set the new IPV6_CHECKSUM socket option to have the kernel (1) + compute and store a checksum for output, and (2) verify the received + checksum on input, discarding the packet if the checksum is in error. + This option prevents applications from having to perform source + address selection on the packets they send. The checksum will + incorporate the IPv6 pseudo-header, defined in Section 8.1 of + [RFC-2460]. This new socket option also specifies an integer offset + into the user data of where the checksum is located. + + int offset = 2; + setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &offset, sizeof(offset)); + + By default, this socket option is disabled. Setting the offset to -1 + also disables the option. By disabled we mean (1) the kernel will + not calculate and store a checksum for outgoing packets, and (2) the + kernel will not verify a checksum for received packets. + + (Note: Since the checksum is always calculated by the kernel for an + ICMPv6 socket, applications are not able to generate ICMPv6 packets + with incorrect checksums (presumably for testing purposes) using this + API.) + + +3.2. ICMPv6 Type Filtering + + ICMPv4 raw sockets receive most ICMPv4 messages received by the + kernel. (We say "most" and not "all" because Berkeley-derived + kernels never pass echo requests, timestamp requests, or address mask + requests to a raw socket. Instead these three messages are processed + entirely by the kernel.) But ICMPv6 is a superset of ICMPv4, also + including the functionality of IGMPv4 and ARPv4. This means that an + ICMPv6 raw socket can potentially receive many more messages than + would be received with an ICMPv4 raw socket: ICMP messages similar to + ICMPv4, along with neighbor solicitations, neighbor advertisements, + and the three 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 + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 17] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + 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 + header. + + The current filter is fetched and stored using getsockopt() and + setsockopt() with a level of IPPROTO_ICMPV6 and an option name of + ICMP6_FILTER. + + Six macros operate on an icmp6_filter structure: + + void ICMP6_FILTER_SETPASSALL (struct icmp6_filter *); + void ICMP6_FILTER_SETBLOCKALL(struct icmp6_filter *); + + void ICMP6_FILTER_SETPASS ( int, struct icmp6_filter *); + void ICMP6_FILTER_SETBLOCK( int, struct icmp6_filter *); + + int ICMP6_FILTER_WILLPASS (int, + const struct icmp6_filter *); + int ICMP6_FILTER_WILLBLOCK(int, + const struct icmp6_filter *); + + The first argument to the last four macros (an integer) is an ICMPv6 + message type, between 0 and 255. The pointer argument to all six + macros is a pointer to a filter that is modified by the first four + macros examined by the last two macros. + + The first two macros, SETPASSALL and SETBLOCKALL, let us specify that + all ICMPv6 messages are passed to the application or that all ICMPv6 + messages are blocked from being passed to the application. + + The next two macros, SETPASS and SETBLOCK, let us specify that + messages of a given ICMPv6 type should be passed to the application + or not passed to the application (blocked). + + The final two macros, WILLPASS and WILLBLOCK, return true or false + depending whether the specified message type is passed to the + application or blocked from being passed to the application by the + filter pointed to by the second argument. + + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 18] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + When an ICMPv6 raw socket is created, it will by default pass all + ICMPv6 message types to the application. + + As an example, a program that wants to receive only router + advertisements could execute the following: + + struct icmp6_filter myfilt; + + fd = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6); + + ICMP6_FILTER_SETBLOCKALL(&myfilt); + ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &myfilt); + setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &myfilt, sizeof(myfilt)); + + The filter structure is declared and then initialized to block all + messages types. The filter structure is then changed to allow router + advertisement messages to be passed to the application and the filter + is installed using setsockopt(). + + The icmp6_filter structure is similar to the fd_set datatype used + with the select() function in the sockets API. The icmp6_filter + structure is an opaque datatype and the application should not care + how it is implemented. All the application does with this datatype + is allocate a variable of this type, pass a pointer to a variable of + this type to getsockopt() and setsockopt(), and operate on a variable + of this type using the six macros that we just defined. + + Nevertheless, it is worth showing a simple implementation of this + datatype and the six macros. + + struct icmp6_filter { + uint32_t icmp6_filt[8]; /* 8*32 = 256 bits */ + }; + + #define ICMP6_FILTER_WILLPASS(type, filterp) \ + ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) != 0) + #define ICMP6_FILTER_WILLBLOCK(type, filterp) \ + ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) == 0) + #define ICMP6_FILTER_SETPASS(type, filterp) \ + ((((filterp)->icmp6_filt[(type) >> 5]) |= (1 << ((type) & 31)))) + #define ICMP6_FILTER_SETBLOCK(type, filterp) \ + ((((filterp)->icmp6_filt[(type) >> 5]) &= ~(1 << ((type) & 31)))) + #define ICMP6_FILTER_SETPASSALL(filterp) \ + memset((filterp), 0xFF, sizeof(struct icmp6_filter)) + #define ICMP6_FILTER_SETBLOCKALL(filterp) \ + memset((filterp), 0, sizeof(struct icmp6_filter)) + + (Note: These sample definitions have two limitations that an + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 19] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + 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: + + 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 effect 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 + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 20] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + 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 implementation dependent + IPPROTO_IPV6 IPV6_HOPOPTS implementation dependent + IPPROTO_IPV6 IPV6_DSTOPTS implementation dependent + IPPROTO_IPV6 IPV6_RTHDRDSTOPTS implementation dependent + + + All these options are described in detail in following sections. All + the constants beginning with IPV6_ are defined as a result of + including the header. + + (Note: We intentionally use the same constant for the cmsg_level + member as is used as the second argument to getsockopt() and + setsockopt() (what is called the "level"), and the same constant for + the cmsg_type member as is used as the third argument to getsockopt() + and setsockopt() (what is called the "option name"). This is + consistent with the existing use of ancillary data in 4.4BSD: + returning the destination address of an IPv4 datagram.) + + (Note: It is up to the implementation what it passes as ancillary + data for the 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 + later. These functions serve two purposes: to simplify the interface + to these features (instead of requiring the application to know the + intimate details of the extension header formats), and to hide the + actual implementation from the application. Nevertheless, we show + some examples of these features that store the actual extension + header as the ancillary data. Implementations need not use this + technique.) + + +4.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 + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 21] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + 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, + 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. If the + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 22] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + application asks for e.g., IPV6_RTHDR and a received datagram does + not contain a Routing header an implementation might either exclude + the IPV6_RTHDR ancillary data item or pass up an item with zero + length (cmsg_data being zero length). 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. 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 + header. + + struct in6_pktinfo { + struct in6_addr ipi6_addr; /* src/dst IPv6 address */ + unsigned int ipi6_ifindex; /* send/recv interface index */ + }; + + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 23] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + 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: + + 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.) + + +5.1. Specifying/Receiving the Interface + + Interfaces on an IPv6 node are identified by a small positive + integer, as described in Section 4 of [RFC-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 + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 24] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + in6_pktinfo structure. + + +5.2. Specifying/Receiving Source/Destination Address + + The source IPv6 address can be specified by calling bind() before + each output operation, but supplying the source address together with + the data requires less overhead (i.e., fewer system calls) and + requires less state to be stored and protected in a multithreaded + application. + + When specifying the source IPv6 address as ancillary data, if the + ipi6_addr member of the in6_pktinfo structure is the unspecified + address (IN6ADDR_ANY_INIT 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. + + +5.3. Specifying/Receiving the Hop Limit + + The outgoing hop limit is normally specified with either the + IPV6_UNICAST_HOPS socket option or the IPV6_MULTICAST_HOPS socket + option, both of which are described in [RFC-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)); + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 25] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + 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 + + x < -1: return an error of EINVAL + x == -1: use kernel default + 0 <= x <= 255: use x + x >= 256: return an error of EINVAL + + + +5.4. Specifying the Next Hop Address + + The IPV6_NEXTHOP ancillary data object specifies the next hop for the + datagram as a socket address structure. In the cmsghdr structure + containing this ancillary data, the cmsg_level member will be + IPPROTO_IPV6, the cmsg_type member will be IPV6_NEXTHOP, and the + first byte of cmsg_data[] will be the first byte of the socket + address structure. + + This is a privileged option. (Note: It is implementation defined and + beyond the scope of this document to define what "privileged" means. + Unix systems use this term to mean the process must have an effective + user ID of 0.) + + If the socket address structure contains an IPv6 address (e.g., the + sin6_family member is AF_INET6), then the node identified by that + address must be a neighbor of the sending host. If that address + equals the destination IPv6 address of the datagram, then this is + equivalent to the existing SO_DONTROUTE socket option. + + +5.5. Additional Errors with sendmsg() 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: + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 26] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + ENXIO The interface specified by ipi6_ifindex does not exist. + + ENETDOWN The interface specified by ipi6_ifindex is not enabled + for IPv6 use. + + EADDRNOTAVAIL ipi6_ifindex specifies an interface but the address + ipi6_addr is not available for use on that interface. + + EHOSTUNREACH No route to the destination exists over the interface + specified by ifi6_ifindex. + + +6. 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. + + 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 all in the + header. + + To receive a Routing header the application must enable the + IPV6_RECVRTHDR socket option: + + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 27] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + + 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 + 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 in the header: + + #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. + + +6.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 + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 28] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + 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.) + + +6.2. inet6_rth_init + + + 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. 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. + + +6.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. + + +6.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-00.txt [Page 29] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + error. + + +6.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. + + +6.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. + + +7. Hop-By-Hop Options + + A variable number of Hop-by-Hop options can appear in a single Hop- + by-Hop options header. Each option in the header is TLV-encoded with + a type, length, and value. + + Today only three Hop-by-Hop options are defined for IPv6 [RFC-2460]: + Jumbo Payload, Pad1, and PadN, although a proposal exists for a + router-alert Hop-by-Hop option. The Jumbo Payload option should not + be passed back to an application and an application should receive an + error if it attempts to set it. This option is processed entirely by + the kernel. It is indirectly specified by datagram-based + applications as the size of the datagram to send and indirectly + passed back to these applications as the length of the received + datagram. The two pad options are for alignment purposes and are + automatically inserted by a sending kernel when needed and ignored by + the receiving kernel. This section of the API is therefore defined + for future Hop-by-Hop options that an application may need to specify + and receive. + + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 30] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + Individual Hop-by-Hop options (and Destination options, which are + described shortly, and which 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. + + +7.1. Receiving Hop-by-Hop Options + + To receive Hop-by-Hop options the application must enable the + IPV6_RECVHOPOPTS socket option: + + 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 + shortly. + + +7.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 + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 31] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + 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 shortly. + + Additional errors may be possible from sendmsg() and setsockopt() if + the specified option is in error. + + +8. 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. + + +8.1. Receiving Destination Options + + 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 + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 32] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + 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. + + +8.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 earlier, 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 + 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 shortly. + + Additional errors may be possible from sendmsg() and setsockopt() if + the specified option is in error. + + +9. Hop-by-Hop and Destination Options Processing + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 33] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + Building and parsing the Hop-by-Hop and Destination options is + complicated for the reasons given earlier. We therefore define a set + of functions to help the application. The function prototypes for + these functions are all in the header. + + 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. + + +9.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 too small or not a multiple of 8 the + function fails and returns -1. + + +9.2. inet6_opt_append + + + 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. + + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 34] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + 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 len + value can not exceed the value of align. + + +9.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 + function returns -1. + + +9.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. + + +9.5. inet6_opt_next + + + + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 35] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + + 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 + previous 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 taking into account + the option that was returned. + + +9.6. inet6_opt_find + + + int inet6_opt_find(void *extbuf, size_t extlen, int prevlen, + uint8_t type, size_t *lenp, + void **databufp); + + 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 taking into account the option + that was returned and any options that didn't match the 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. + + +9.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. + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 36] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + The function returns the offset for the next field (i.e., offset + + vallen) which can be used when extracting option content with + multiple fields. + + +10. 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 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. + + +11. 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-00.txt [Page 37] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 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. + + +12. Extended interfaces for rresvport, rcmd and rexec + + TBD + + +12.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 IPv4/TCP socket, it can also create an + IPv6/TCP socket. The family argument is either AF_INET or AF_INET6, + and a new error return is EAFNOSUPPORT if the address family is not + supported. + + (Note: There is little consensus on which header defines the + rresvport() and rcmd() function prototypes. 4.4BSD defines it in + , others in , and others don't define the function + prototypes at all.) + + +12.2. rcmd_af + + TBD + + int rcmd_af(char **ahost, unsigned short rport, const char *locuser, + const char *remuser, const char *cmd, int *fd2p, int af) + + + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 38] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + +12.3. rexec_af + + TBD + + int rexec_af(char **ahost, unsigned short rport, const char *name, + const char *pass, const char *cmd, int *fd2p, int af) + + + +13. Future Items + + Some additional items may require standardization, but no concrete + proposals have been made for the API to perform these tasks. These + may be addressed in a later document. + + +13.1. Flow Labels + + Earlier revisions of this document specified a set of + inet6_flow_XXX() functions to assign, share, and free IPv6 flow + labels. Consensus, however, indicated that it was premature to + specify this part of the API. + + +13.2. Path MTU Discovery and UDP + + A standard method may be desirable for a UDP application to determine + the "maximum send transport-message size" (Section 5.1 of [RFC-1981]) + to a given destination. This would let the UDP application send + smaller datagrams to the destination, avoiding fragmentation. + + +13.3. Neighbor Reachability and UDP + + A standard method may be desirable for a UDP application to tell the + kernel that it is making forward progress with a given peer (Section + 7.3.1 of [RFC-2461]). This could save unneeded neighbor + solicitations and neighbor advertisements. + + +14. 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 + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 39] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + ICMP6_DST_UNREACH_NOPORT + ICMP6_DST_UNREACH_NOROUTE + ICMP6_DST_UNREACH_NOTNEIGHBOR + 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 + 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 + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 40] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + IPPROTO_DSTOPTS + IPPROTO_ESP + IPPROTO_FRAGMENT + IPPROTO_HOPOPTS + IPPROTO_ICMPV6 + IPPROTO_IPV6 + IPPROTO_NONE + IPPROTO_ROUTING + IPV6_RECVDSTOPTS + IPV6_RECVHOPLIMIT + IPV6_RECVHOPOPTS + IPV6_RECVPKTINFO + IPV6_RECVRTHDR + IPV6_RECVRTHDRDSTOPTS + IPV6_DSTOPTS + IPV6_HOPLIMIT + IPV6_HOPOPTS + IPV6_NEXTHOP + IPV6_PKTINFO + IPV6_RTHDR + IPV6_RTHDRDSTOPTS + IPV6_RTHDR_TYPE_0 + 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, + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 41] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + 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); + 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); + + + +15. 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 + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 42] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + must be prevented; at least for non-privileged processes. + + +16. Compatibility with RFC 2292 + + The intent is that implementations that so desire should be able to + conform to both this document and to RFC 2292. + + This is possible since this document doesn't redefine any of the + existing socket options and since it uses new names for the + inet6_XXX() functions that take different arguments. + + Thus implementations that wish to provide support for RFC 2292 can + retain the support for IPV6_PKTOPTIONS, allow the setting of + IPV6_RTHDR etc to a sizeof(int) value to enable receipt of ancillary + data, and provide the old (as well as the new) inet6_XXX() functions. + + +17. Change History + + Changes from RFC 2292: + + - Removed the IPV6_PKTOPTIONS socket option by allowing sticky + 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. + + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 43] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + - 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". + + - 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(). + + +18. TODO and Open Issues + + Items left to do: + + - Add mechanism to avoid fragmentation by sending at the minimum + IPv6 MTU. Suggest an IPV6_USE_MIN_MTU socket option. + + - Add MTU notification so that UDP and raw socket applications can + participate in path MTU discovery. Suggest an ancillary data + item which might be received without any data (i.e. recvmsg + returns zero): IPV6_PATHMTU The receipt of this ancillary data + item is enabled with IPV6_RECVPATHMTU. + + - Add Reachability confirmation for UDP and raw socket + applications. Suggest an ancillary data item for sendmsg() + called IPV6_REACHCONF which takes no value (i.e. it is zero + length). + + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 44] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + Open issues: + + - Should we make the content of IPV6_RTHDR, IPV6_HOPOPTS etc be + specified as the extension header format (struct ip6_rthdr etc) + instead of the current "implementation dependent"? + + - Are the new inet6_opt_set_val() and inet6_opt_get_val() useful? + There implementation is just an assignment/bcopy based on the + length of the data item. + + - "If the application asks for e.g., IPV6_RTHDR and a received + datagram does not contain a Routing header an implementation + might either exclude the IPV6_RTHDR ancillary data item or pass + up an item with zero length (cmsg_data being zero length)." + Discussion: Do we want the above behavior? Or always exclude the + ancillary data item? + + - Should we add option definitions (IPV6OPT_PAD1 etc) and all the + different flags for the headers defined in section 2? + + - "Note that if any ancillary data is specified in a call to + sendmsg(), all of the sticky options are overridden for that + datagram." We could instead define that a zero-length cmsghdr + (for the specific level and type) is needed to override an + individual sticky options instead. Should we? + + - The examples use CMSG_LEN and CMSG_SPACE interchangeably. The + latter only needs to be used when there are multiple ancillary + data items in a control buffer. This should be clarified + somewhere. + + +19. References + + + [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 + + + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 45] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + 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, Matt + Crawford, Sam T. Denton, Richard Draves, Francis Dupont, Bob + Gilligan, Tim Hartrick, Masaki Hirabaru, Yoshinobu Inoue, Mukesh + Kacker, A. N. Kuznetsov, Pedro Marques, Jack McCann, der Mouse, John + Moy, Thomas Narten, Steve Parker, Charles Perkins, Tom Pusateri, + Pedro Roque, Sameer Shah, Peter Sjodin, Stephen P. Spackman, Jinmei + Tatuya, Karen Tracey, Quaizar Vohra, Carl Williams, Steve Wise, and + Kazu Yamamoto. + + +21. Authors' Addresses + + W. Richard Stevens + 1202 E. Paseo del Zorro + Tucson, AZ 85718 + Email: rstevens@kohala.com + + + 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 + + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 46] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + 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: + + 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 + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 47] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + 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[]; */ + }; + + 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 shortly. 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. + + + + + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 48] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + + |<--------------------------- 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 + 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(). + + + + + + + + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 49] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + + 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 the by msghdr structure (that + is, if either msg_control is NULL or if msg_controllen is less than + the size of a cmsghdr structure). + + One possible implementation could be + + #define CMSG_FIRSTHDR(mhdr) \ + ( (mhdr)->msg_controllen >= sizeof(struct cmsghdr) ? \ + (struct cmsghdr *)(mhdr)->msg_control : \ + (struct cmsghdr *)NULL ) + + (Note: Most existing implementations do not test the value of + msg_controllen, and just return the value of msg_control. The value + of msg_controllen must be tested, because if the application asks + recvmsg() to return ancillary data, by setting msg_control to point + to the application's buffer and setting msg_controllen to the length + of this buffer, the kernel indicates that no ancillary data is + available by setting msg_controllen to 0 on return. It is also + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 50] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + 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: + + 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: + + + + + + + + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 51] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + + #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: + + #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, to allocate space dynamically for the ancillary + data. This macro should not be used to initialize the cmsg_len + member of a cmsghdr structure; instead use the CMSG_LEN() macro. + + One possible implementation could be: + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 52] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + + #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 + 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 + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 53] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + 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: + + 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_LEN(extlen); + cmsgptr = malloc(cmsglen); + cmsgptr->cmsg_len = cmsglen; + 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 + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 54] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + 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 + 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-00.txt [Page 55] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 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-00.txt [Page 56] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 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-00.txt [Page 57] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 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-00.txt [Page 58] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 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-00.txt [Page 59] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 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-00.txt [Page 60] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 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-00.txt [Page 61] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 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 IPV6OPT_PAD1: + printf("PAD1\n"); + break; + case IPV6OPT_PADN: + printf("PADN (N=%d)\n", len + 2); + break; + case OPT_X: + offset = 0; + offset = inet6_opt_get_val(databuf, offset, + &value4, sizeof (value4)); + + + +draft-ietf-ipngwg-2292bis-00.txt [Page 62] + +INTERNET-DRAFT Advanced Sockets API for IPv6 June 24, 1999 + + + 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: + 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-00.txt [Page 63] + diff --git a/doc/draft/draft-ietf-ipngwg-bsd-api-new-06.txt b/doc/draft/draft-ietf-ipngwg-bsd-api-new-06.txt deleted file mode 100644 index ffcfb0e6d2..0000000000 --- a/doc/draft/draft-ietf-ipngwg-bsd-api-new-06.txt +++ /dev/null @@ -1,2176 +0,0 @@ - -Internet Engineering Task Force R.E. Gilligan (FreeGate) -INTERNET-DRAFT S. Thomson (Bellcore) -Obsoletes RFC 2133 Jim Bound (Compaq) - W. R. Stevens (Consultant) - January 25, 1999 - - - - - - - Basic Socket Interface Extensions for IPv6 - - - - -Status of this Memo - - This document is a submission by the Internet Protocol IPv6 - Working Group of the Internet Engineering Task Force (IETF). - Comments should be submitted to the ipng@sunroof.eng.sun.com - mailing list. - - This document is an Internet-Draft. 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 time. It is inappropriate to use Internet- - Drafts as reference material or to cite them other than as - "work in progress." - - To view the entire list of current Internet-Drafts, please check - the "1id-abstracts.txt" listing contained in the Internet-Drafts - Shadow Directories on ftp.is.co.za (Africa), ftp.nordu.net - (Europe), munnari.oz.au (Pacific Rim), ftp.ietf.org (US East - Coast), or ftp.isi.edu (US West Coast). - - Distribution of this memo is unlimited. - - -Abstract - -The de facto standard application program interface (API) for TCP/IP -applications is the "sockets" interface. Although this API was -developed for Unix in the early 1980s it has also been implemented on a -wide variety of non-Unix systems. TCP/IP applications written using the -sockets API have in the past enjoyed a high degree of portability and we -would like the same portability with IPv6 applications. But changes are -required to the sockets API to support IPv6 and this memo describes -these changes. These include a new socket address structure to carry -IPv6 addresses, new address conversion functions, and some new socket -options. These extensions are designed to provide access to the basic -IPv6 features required by TCP and UDP applications, including -multicasting, while introducing a minimum of change into the system and -providing complete compatibility for existing IPv4 applications. -Additional extensions for advanced IPv6 features (raw sockets and access -to the IPv6 extension headers) are defined in another document [4]. - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 1] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - -Table of Contents: - -1. Introduction.................................................3 -2. Design Considerations........................................3 -2.1 What Needs to be Changed....................................3 -2.2 Data Types..................................................5 -2.3 Headers.....................................................5 -2.4 Structures..................................................5 -3. Socket Interface.............................................5 -3.1 IPv6 Address Family and Protocol Family.....................5 -3.2 IPv6 Address Structure......................................6 -3.3 Socket Address Structure for 4.3BSD-Based Systems...........6 -3.4 Socket Address Structure for 4.4BSD-Based Systems...........7 -3.5 The Socket Functions........................................8 -3.6 Compatibility with IPv4 Applications........................9 -3.7 Compatibility with IPv4 Nodes...............................9 -3.8 IPv6 Wildcard Address......................................10 -3.9 IPv6 Loopback Address......................................11 -3.10 Portability Additions.....................................11 -4. Interface Identification....................................13 -4.1 Name-to-Index..............................................14 -4.2 Index-to-Name..............................................14 -4.3 Return All Interface Names and Indexes.....................15 -4.4 Free Memory................................................15 -5. Socket Options..............................................15 -5.1 Unicast Hop Limit..........................................16 -5.2 Sending and Receiving Multicast Packets....................16 -6. Library Functions...........................................18 -6.1 Nodename-to-Address Translation............................18 -6.2 Address-To-Nodename Translation............................21 -6.3 Freeing memory for getipnodebyname and getipnodebyaddr.....22 -6.4 Protocol-Independent Nodename and Service Name Translation.22 -6.5 Socket Address Structure to Nodename and Service Name......25 -6.6 Address Conversion Functions...............................26 -6.7 Address Testing Macros.....................................27 -7. Summary of New Definitions..................................28 -8. Security Considerations.....................................29 -9. Year 2000 Considerations....................................29 -Changes From RFC 2133..........................................30 -Acknowledgments................................................32 -References.....................................................33 -Authors' Addresses.............................................33 - - - - - - - - - - - - - - - - - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 2] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - -1. Introduction - -While IPv4 addresses are 32 bits long, IPv6 interfaces are identified by -128-bit addresses. The socket interface makes the size of an IP address -quite visible to an application; virtually all TCP/IP applications for -BSD-based systems have knowledge of the size of an IP address. Those -parts of the API that expose the addresses must be changed to -accommodate the larger IPv6 address size. IPv6 also introduces new -features (e.g., traffic class and flowlabel), some of which must be made -visible to applications via the API. This memo defines a set of -extensions to the socket interface to support the larger address size -and new features of IPv6. - - - -2. Design Considerations - -There are a number of important considerations in designing changes to -this well-worn API: - - - The API changes should provide both source and binary - compatibility for programs written to the original API. That - is, existing program binaries should continue to operate when - run on a system supporting the new API. In addition, existing - applications that are re-compiled and run on a system supporting - the new API should continue to operate. Simply put, the API - changes for IPv6 should not break existing programs. An additonal - mechanism for implementations to verify this is to verify the new - symbols are protected by Feature Test Macros as described in IEEE Std - 1003.1. (Such Feature Test Macros are not defined by this RFC.) - - - The changes to the API should be as small as possible in order - to simplify the task of converting existing IPv4 applications to - IPv6. - - - Where possible, applications should be able to use this - API to interoperate with both IPv6 and IPv4 hosts. Applications - should not need to know which type of host they are - communicating with. - - - IPv6 addresses carried in data structures should be 64-bit - aligned. This is necessary in order to obtain optimum - performance on 64-bit machine architectures. - -Because of the importance of providing IPv4 compatibility in the API, -these extensions are explicitly designed to operate on machines that -provide complete support for both IPv4 and IPv6. A subset of this API -could probably be designed for operation on systems that support only -IPv6. However, this is not addressed in this memo. - - - -2.1 What Needs to be Changed - -The socket interface API consists of a few distinct components: - - - Core socket functions. - - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 3] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - - - Address data structures. - - - Name-to-address translation functions. - - - Address conversion functions. - -The core socket functions -- those functions that deal with such things -as setting up and tearing down TCP connections, and sending and -receiving UDP packets -- were designed to be transport independent. -Where protocol addresses are passed as function arguments, they are -carried via opaque pointers. A protocol-specific address data structure -is defined for each protocol that the socket functions support. -Applications must cast pointers to these protocol-specific address -structures into pointers to the generic "sockaddr" address structure -when using the socket functions. These functions need not change for -IPv6, but a new IPv6-specific address data structure is needed. - -The "sockaddr_in" structure is the protocol-specific data structure for -IPv4. This data structure actually includes 8-octets of unused space, -and it is tempting to try to use this space to adapt the sockaddr_in -structure to IPv6. Unfortunately, the sockaddr_in structure is not -large enough to hold the 16-octet IPv6 address as well as the other -information (address family and port number) that is needed. So a new -address data structure must be defined for IPv6. - -IPv6 addresses are scoped [2] so they could be link-local, site, -organization, global, or other scopes at this time undefined. To -support applications that want to be able to identify a set of -interfaces for a specific scope, the IPv6 sockaddr_in structure must -support a field that can be used by an implementation to identify a set -of interfaces identifying the scope for an IPv6 address. - -The name-to-address translation functions in the socket interface are -gethostbyname() and gethostbyaddr(). These are left as is and new -functions are defined to support IPv4 and IPv6. Additionally, the POSIX -1003.g draft [3] specifies a new nodename-to-address translation -function which is protocol independent. This function can also be used -with IPv4 and IPv6. - -The address conversion functions -- inet_ntoa() and inet_addr() -- -convert IPv4 addresses between binary and printable form. These -functions are quite specific to 32-bit IPv4 addresses. We have designed -two analogous functions that convert both IPv4 and IPv6 addresses, and -carry an address type parameter so that they can be extended to other -protocol families as well. - -Finally, a few miscellaneous features are needed to support IPv6. New -interfaces are needed to support the IPv6 traffic class, flow label, and -hop limit header fields. New socket options are needed to control the -sending and receiving of IPv6 multicast packets. - -The socket interface will be enhanced in the future to provide access to -other IPv6 features. These extensions are described in [4]. - - - - - - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 4] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - -2.2 Data Types - -The data types of the structure elements given in this memo are intended -to be examples, not absolute requirements. Whenever possible, data -types from Draft 6.6 (March 1997) of POSIX 1003.1g are used: uintN_t -means an unsigned integer of exactly N bits (e.g., uint16_t). We also -assume the argument data types from 1003.1g when possible (e.g., the -final argument to setsockopt() is a size_t value). Whenever buffer -sizes are specified, the POSIX 1003.1 size_t data type is used (e.g., -the two length arguments to getnameinfo()). - - - -2.3 Headers - -When function prototypes and structures are shown we show the headers -that must be #included to cause that item to be defined. - - - -2.4 Structures - -When structures are described the members shown are the ones that must -appear in an implementation. Additional, nonstandard members may also -be defined by an implementation. As an additional precaution -nonstandard members could be verified by Feature Test Macros as -described in IEEE Std 1003.1. (Such Feature Test Macros are not defined -by this RFC.) - -The ordering shown for the members of a structure is the recommended -ordering, given alignment considerations of multibyte members, but an -implementation may order the members differently. - - - -3. Socket Interface - -This section specifies the socket interface changes for IPv6. - - - -3.1 IPv6 Address Family and Protocol Family - -A new address family name, AF_INET6, is defined in . The -AF_INET6 definition distinguishes between the original sockaddr_in -address data structure, and the new sockaddr_in6 data structure. - -A new protocol family name, PF_INET6, is defined in . -Like most of the other protocol family names, this will usually be -defined to have the same value as the corresponding address family name: - - #define PF_INET6 AF_INET6 - -The PF_INET6 is used in the first argument to the socket() function to -indicate that an IPv6 socket is being created. - - - - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 5] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - -3.2 IPv6 Address Structure - -A new in6_addr structure holds a single IPv6 address and is defined as a -result of including : - - struct in6_addr { - uint8_t s6_addr[16]; /* IPv6 address */ - }; - -This data structure contains an array of sixteen 8-bit elements, which -make up one 128-bit IPv6 address. The IPv6 address is stored in network -byte order. - -The structure in6_addr above is usually implemented with an embedded -union with extra fields that force the desired alignment level in a -manner similar to BSD implementations of "struct in_addr". Those -additional implementation details are omitted here for simplicity. - -An example is as follows: - -struct in6_addr { - union { - uint8_t _S6_u8[16]; - uint32_t _S6_u32[4]; - uint64_t _S6_u64[2]; - } _S6_un; -}; -#define s6_addr _S6_un._S6_u8 - - - -3.3 Socket Address Structure for 4.3BSD-Based Systems - -In the socket interface, a different protocol-specific data structure is -defined to carry the addresses for each protocol suite. Each protocol- -specific data structure is designed so it can be cast into a protocol- -independent data structure -- the "sockaddr" structure. Each has a -"family" field that overlays the "sa_family" of the sockaddr data -structure. This field identifies the type of the data structure. - -The sockaddr_in structure is the protocol-specific address data -structure for IPv4. It is used to pass addresses between applications -and the system in the socket functions. The following sockaddr_in6 -structure holds IPv6 addresses and is defined as a result of including -the header: - - struct sockaddr_in6 { - sa_family_t sin6_family; /* AF_INET6 */ - in_port_t sin6_port; /* transport layer port # */ - uint32_t sin6_flowinfo; /* IPv6 traffic class & flow info */ - struct in6_addr sin6_addr; /* IPv6 address */ - uint32_t sin6_scope_id; /* set of interfaces for a scope */ - }; - -This structure is designed to be compatible with the sockaddr data -structure used in the 4.3BSD release. - -The sin6_family field identifies this as a sockaddr_in6 structure. This - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 6] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - -field overlays the sa_family field when the buffer is cast to a sockaddr -data structure. The value of this field must be AF_INET6. - -The sin6_port field contains the 16-bit UDP or TCP port number. This -field is used in the same way as the sin_port field of the sockaddr_in -structure. The port number is stored in network byte order. - -The sin6_flowinfo field is a 32-bit field that contains two pieces of -information: the traffic class and the flow label. The contents and -interpretation of this member is specified in [1]. The sin6_flowinfo -field SHOULD be set to zero by an implementation prior to using the -sockaddr_in6 structure by an application on receive operations. - -The sin6_addr field is a single in6_addr structure (defined in the -previous section). This field holds one 128-bit IPv6 address. The -address is stored in network byte order. - -The ordering of elements in this structure is specifically designed so -that when sin6_addr field is aligned on a 64-bit boundary, the start of -the structure will also be aligned on a 64-bit boundary. This is done -for optimum performance on 64-bit architectures. - -The sin6_scope_id field is a 32-bit integer that identifies a set of -interfaces as appropriate for the scope of the address carried in the -sin6_addr field. For a link scope sin6_addr sin6_scope_id would be an -interface index. For a site scope sin6_addr, sin6_scope_id would be a -site identifier. The mapping of sin6_scope_id to an interface or set of -interfaces is left to implementation and future specifications on the -subject of site identifiers. - -Notice that the sockaddr_in6 structure will normally be larger than the -generic sockaddr structure. On many existing implementations the -sizeof(struct sockaddr_in) equals sizeof(struct sockaddr), with both -being 16 bytes. Any existing code that makes this assumption needs to -be examined carefully when converting to IPv6. - - - -3.4 Socket Address Structure for 4.4BSD-Based Systems - -The 4.4BSD release includes a small, but incompatible change to the -socket interface. The "sa_family" field of the sockaddr data structure -was changed from a 16-bit value to an 8-bit value, and the space saved -used to hold a length field, named "sa_len". The sockaddr_in6 data -structure given in the previous section cannot be correctly cast into -the newer sockaddr data structure. For this reason, the following -alternative IPv6 address data structure is provided to be used on -systems based on 4.4BSD. It is defined as a result of including the - header. - - struct sockaddr_in6 { - uint8_t sin6_len; /* length of this struct */ - sa_family_t sin6_family; /* AF_INET6 */ - in_port_t sin6_port; /* transport layer port # */ - uint32_t sin6_flowinfo; /* IPv6 flow information */ - struct in6_addr sin6_addr; /* IPv6 address */ - uint32_t sin6_scope_id; /* set of interfaces for a scope */ - }; - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 7] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - -The only differences between this data structure and the 4.3BSD variant -are the inclusion of the length field, and the change of the family -field to a 8-bit data type. The definitions of all the other fields are -identical to the structure defined in the previous section. - -Systems that provide this version of the sockaddr_in6 data structure -must also declare SIN6_LEN as a result of including the -header. This macro allows applications to determine whether they are -being built on a system that supports the 4.3BSD or 4.4BSD variants of -the data structure. - - - -3.5 The Socket Functions - -Applications call the socket() function to create a socket descriptor -that represents a communication endpoint. The arguments to the socket() -function tell the system which protocol to use, and what format address -structure will be used in subsequent functions. For example, to create -an IPv4/TCP socket, applications make the call: - - s = socket(PF_INET, SOCK_STREAM, 0); - -To create an IPv4/UDP socket, applications make the call: - - s = socket(PF_INET, SOCK_DGRAM, 0); - -Applications may create IPv6/TCP and IPv6/UDP sockets by simply using -the constant PF_INET6 instead of PF_INET in the first argument. For -example, to create an IPv6/TCP socket, applications make the call: - - s = socket(PF_INET6, SOCK_STREAM, 0); - -To create an IPv6/UDP socket, applications make the call: - - s = socket(PF_INET6, SOCK_DGRAM, 0); - -Once the application has created a PF_INET6 socket, it must use the -sockaddr_in6 address structure when passing addresses in to the system. -The functions that the application uses to pass addresses into the -system are: - - bind() - connect() - sendmsg() - sendto() - -The system will use the sockaddr_in6 address structure to return -addresses to applications that are using PF_INET6 sockets. The -functions that return an address from the system to an application are: - - accept() - recvfrom() - recvmsg() - getpeername() - getsockname() - -No changes to the syntax of the socket functions are needed to support - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 8] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - -IPv6, since all of the "address carrying" functions use an opaque -address pointer, and carry an address length as a function argument. - - - -3.6 Compatibility with IPv4 Applications - -In order to support the large base of applications using the original -API, system implementations must provide complete source and binary -compatibility with the original API. This means that systems must -continue to support PF_INET sockets and the sockaddr_in address -structure. Applications must be able to create IPv4/TCP and IPv4/UDP -sockets using the PF_INET constant in the socket() function, as -described in the previous section. Applications should be able to hold -a combination of IPv4/TCP, IPv4/UDP, IPv6/TCP and IPv6/UDP sockets -simultaneously within the same process. - -Applications using the original API should continue to operate as they -did on systems supporting only IPv4. That is, they should continue to -interoperate with IPv4 nodes. - - - -3.7 Compatibility with IPv4 Nodes - -The API also provides a different type of compatibility: the ability for -IPv6 applications to interoperate with IPv4 applications. This feature -uses the IPv4-mapped IPv6 address format defined in the IPv6 addressing -architecture specification [2]. This address format allows the IPv4 -address of an IPv4 node to be represented as an IPv6 address. The IPv4 -address is encoded into the low-order 32 bits of the IPv6 address, and -the high-order 96 bits hold the fixed prefix 0:0:0:0:0:FFFF. IPv4- -mapped addresses are written as follows: - - ::FFFF: - -These addresses can be generated automatically by the getipnodebyname() -function when the specified host has only IPv4 addresses (as described -in Section 6.1). - -Applications may use PF_INET6 sockets to open TCP connections to IPv4 -nodes, or send UDP packets to IPv4 nodes, by simply encoding the -destination's IPv4 address as an IPv4-mapped IPv6 address, and passing -that address, within a sockaddr_in6 structure, in the connect() or -sendto() call. When applications use PF_INET6 sockets to accept TCP -connections from IPv4 nodes, or receive UDP packets from IPv4 nodes, the -system returns the peer's address to the application in the accept(), -recvfrom(), or getpeername() call using a sockaddr_in6 structure encoded -this way. - -Few applications will likely need to know which type of node they are -interoperating with. However, for those applications that do need to -know, the IN6_IS_ADDR_V4MAPPED() macro, defined in Section 6.7, is -provided. - - - - - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 9] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - -3.8 IPv6 Wildcard Address - -While the bind() function allows applications to select the source IP -address of UDP packets and TCP connections, applications often want the -system to select the source address for them. With IPv4, one specifies -the address as the symbolic constant INADDR_ANY (called the "wildcard" -address) in the bind() call, or simply omits the bind() entirely. - -Since the IPv6 address type is a structure (struct in6_addr), a symbolic -constant can be used to initialize an IPv6 address variable, but cannot -be used in an assignment. Therefore systems provide the IPv6 wildcard -address in two forms. - -The first version is a global variable named "in6addr_any" that is an -in6_addr structure. The extern declaration for this variable is defined -in : - - extern const struct in6_addr in6addr_any; - -Applications use in6addr_any similarly to the way they use INADDR_ANY in -IPv4. For example, to bind a socket to port number 23, but let the -system select the source address, an application could use the following -code: - - struct sockaddr_in6 sin6; - . . . - sin6.sin6_family = AF_INET6; - sin6.sin6_flowinfo = 0; - sin6.sin6_port = htons(23); - sin6.sin6_addr = in6addr_any; /* structure assignment */ - . . . - if (bind(s, (struct sockaddr *) &sin6, sizeof(sin6)) == -1) - . . . - -The other version is a symbolic constant named IN6ADDR_ANY_INIT and is -defined in . This constant can be used to initialize an -in6_addr structure: - - struct in6_addr anyaddr = IN6ADDR_ANY_INIT; - -Note that this constant can be used ONLY at declaration time. It can -not be used to assign a previously declared in6_addr structure. For -example, the following code will not work: - - /* This is the WRONG way to assign an unspecified address */ - struct sockaddr_in6 sin6; - . . . - sin6.sin6_addr = IN6ADDR_ANY_INIT; /* will NOT compile */ - -Be aware that the IPv4 INADDR_xxx constants are all defined in host byte -order but the IPv6 IN6ADDR_xxx constants and the IPv6 in6addr_xxx -externals are defined in network byte order. - - - - - - - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 10] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - -3.9 IPv6 Loopback Address - -Applications may need to send UDP packets to, or originate TCP -connections to, services residing on the local node. In IPv4, they can -do this by using the constant IPv4 address INADDR_LOOPBACK in their -connect(), sendto(), or sendmsg() call. - -IPv6 also provides a loopback address to contact local TCP and UDP -services. Like the unspecified address, the IPv6 loopback address is -provided in two forms -- a global variable and a symbolic constant. - -The global variable is an in6_addr structure named "in6addr_loopback." -The extern declaration for this variable is defined in : - - extern const struct in6_addr in6addr_loopback; - -Applications use in6addr_loopback as they would use INADDR_LOOPBACK in -IPv4 applications (but beware of the byte ordering difference mentioned -at the end of the previous section). For example, to open a TCP -connection to the local telnet server, an application could use the -following code: - - struct sockaddr_in6 sin6; - . . . - sin6.sin6_family = AF_INET6; - sin6.sin6_flowinfo = 0; - sin6.sin6_port = htons(23); - sin6.sin6_addr = in6addr_loopback; /* structure assignment */ - . . . - if (connect(s, (struct sockaddr *) &sin6, sizeof(sin6)) == -1) - . . . - -The symbolic constant is named IN6ADDR_LOOPBACK_INIT and is defined in -. It can be used at declaration time ONLY; for example: - - struct in6_addr loopbackaddr = IN6ADDR_LOOPBACK_INIT; - -Like IN6ADDR_ANY_INIT, this constant cannot be used in an assignment to -a previously declared IPv6 address variable. - - - -3.10 Portability Additions - -One simple addition to the sockets API that can help application writers -is the "struct sockaddr_storage". This data structure can simplify -writing code portable across multiple address families and platforms. -This data structure is designed with the following goals. - - - It has a large enough implementation specific maximum size to store - the desired set of protocol specific socket address data structures. - Specifically, it is at least large enough to accommodate sockaddr_in - and sockaddr_in6 and possibly other protocol specific socket - addresses too. - - It is aligned at an appropriate boundary so protocol specific socket - address data structure pointers can be cast to it and access their - fields without alignment problems. (e.g. pointers to sockaddr_in6 - and/or sockaddr_in can be cast to it and access fields without alignment - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 11] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - - problems). - - It has the initial field(s) isomorphic to the fields of the - "struct sockaddr" data structure on that implementation which - can be used as a discriminants for deriving the protocol in use. - These initial field(s) would on most implementations either be a - single field of type "sa_family_t" (isomorphic to sa_family field, - 16 bits) or two fields of type uint8_t and sa_family_t respectively, - (isomorphic to sa_len and sa_family_t, 8 bits each). - -An example implementation design of such a data structure would be as -follows. - -/* - * Desired design of maximum size and alignment - */ -#define _SS_MAXSIZE 128 /* Implementation specific max size */ -#define _SS_ALIGNSIZE (sizeof (int64_t)) - /* Implementation specific desired alignment */ -/* - * Definitions used for sockaddr_storage structure paddings design. - */ -#define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof (sa_family_t)) -#define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof (sa_family_t)+ - _SS_PAD1SIZE + _SS_ALIGNSIZE)) -struct sockaddr_storage { - sa_family_t __ss_family; /* address family */ - /* Following fields are implementation specific */ - char __ss_pad1[_SS_PAD1SIZE]; - /* 6 byte pad, this is to make implementation - /* specific pad up to alignment field that */ - /* follows explicit in the data structure */ - int64_t __ss_align; /* field to force desired structure */ - /* storage alignment */ - char __ss_pad2[_SS_PAD2SIZE]; - /* 112 byte pad to achieve desired size, */ - /* _SS_MAXSIZE value minus size of ss_family */ - /* __ss_pad1, __ss_align fields is 112 */ -}; - -On implementations where sockaddr data structure includes a "sa_len", -field this data structure would look like this: - -/* - * Definitions used for sockaddr_storage structure paddings design. - */ -#define _SS_PAD1SIZE (_SS_ALIGNSIZE - - (sizeof (uint8_t) + sizeof (sa_family_t)) -#define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof (sa_family_t)+ - _SS_PAD1SIZE + _SS_ALIGNSIZE)) -struct sockaddr_storage { - uint8_t __ss_len; /* address length */ - sa_family_t __ss_family; /* address family */ - /* Following fields are implementation specific */ - char __ss_pad1[_SS_PAD1SIZE]; - /* 6 byte pad, this is to make implementation - /* specific pad up to alignment field that */ - /* follows explicit in the data structure */ - int64_t __ss_align; /* field to force desired structure */ - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 12] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - - /* storage alignment */ - char __ss_pad2[_SS_PAD2SIZE]; - /* 112 byte pad to achieve desired size, */ - /* _SS_MAXSIZE value minus size of ss_len, */ - /* __ss_family, __ss_pad1, __ss_align fields is 112 */ -}; - -The above example implementation illustrates a data structure which will -align on a 64 bit boundary. An implementation specific field -"__ss_align" along "__ss_pad1" is used to force a 64-bit alignment which -covers proper alignment good enough for needs of sockaddr_in6 (IPv6), -sockaddr_in (IPv4) address data structures. The size of padding fields -__ss_pad1 depends on the chosen alignment boundary. The size of padding -field __ss_pad2 depends on the value of overall size chosen for the -total size of the structure. This size and alignment are represented in -the above example by implementation specific (not required) constants -_SS_MAXSIZE (chosen value 128) and _SS_ALIGNMENT (with chosen value 8). -Constants _SS_PAD1SIZE (derived value 6) and _SS_PAD2SIZE (derived value -112) are also for illustration and not required. The implementation -specific definitions and structure field names above start with an -underscore to denote implementation private namespace. Portable code is -not expected to access or reference those fields or constants. - -The sockaddr_storage structure solves the problem of declaring storage -for automatic variables which is large enough and aligned enough for -storing socket address data structure of any family. For example, code -with a file descriptor and without the context of the address family can -pass a pointer to a variable of this type where a pointer to a socket -address structure is expected in calls such as getpeername() and -determine the address family by accessing the received content after the -call. - -The sockaddr_storage structure may also be useful and applied to certain -other interfaces where a generic socket address large enough and aligned -for use with multiple address families may be needed. A discussion of -those interfaces is outside the scope of this document. - -Also, much existing code assumes that any socket address structure can -fit in a generic sockaddr structure. While this has been true for IPv4 -socket address structures, it has always been false for Unix domain -socket address structures (but in practice this has not been a problem) -and it is also false for IPv6 socket address structures (which can be a -problem). - -So now an application can do the following: - - struct sockaddr_storage __ss; - struct sockaddr_in6 *sin6; - sin6 = (struct sockaddr_in6 *) &__ss; - - - -4. Interface Identification - -This API uses an interface index (a small positive integer) to identify -the local interface on which a multicast group is joined (Section 5.3). -Additionally, the advanced API [4] uses these same interface indexes to -identify the interface on which a datagram is received, or to specify - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 13] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - -the interface on which a datagram is to be sent. - -Interfaces are normally known by names such as "le0", "sl1", "ppp2", and -the like. On Berkeley-derived implementations, when an interface is -made known to the system, the kernel assigns a unique positive integer -value (called the interface index) to that interface. These are small -positive integers that start at 1. (Note that 0 is never used for an -interface index.) There may be gaps so that there is no current -interface for a particular positive interface index. - -This API defines two functions that map between an interface name and -index, a third function that returns all the interface names and -indexes, and a fourth function to return the dynamic memory allocated by -the previous function. How these functions are implemented is left up -to the implementation. 4.4BSD implementations can implement these -functions using the existing sysctl() function with the NET_RT_IFLIST -command. Other implementations may wish to use ioctl() for this -purpose. - - - -4.1 Name-to-Index - -The first function maps an interface name into its corresponding index. - - #include - - unsigned int if_nametoindex(const char *ifname); - -If the specified interface name does not exist, the return value is 0, -and errno is set to ENXIO. If there was a system error (such as -running out of memory), the return value is 0 and errno is set to the -proper value (e.g., ENOMEM). - - - -4.2 Index-to-Name - -The second function maps an interface index into its corresponding name. - - #include - - char *if_indextoname(unsigned int ifindex, char *ifname); - -The ifname argument must point to a buffer of at least IF_NAMESIZE bytes -into which the interface name corresponding to the specified index is -returned. (IF_NAMESIZE is also defined in and its value -includes a terminating null byte at the end of the interface name.) This -pointer is also the return value of the function. If there is no -interface corresponding to the specified index, NULL is returned, and -errno is set to ENXIO, if there was a system error (such as running out -of memory), if_indextoname returns NULL and errno would be set to the -proper value (e.g., ENOMEM). - - - - - - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 14] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - -4.3 Return All Interface Names and Indexes - -The if_nameindex structure holds the information about a single -interface and is defined as a result of including the header. - - struct if_nameindex { - unsigned int if_index; /* 1, 2, ... */ - char *if_name; /* null terminated name: "le0", ... */ - }; - -The final function returns an array of if_nameindex structures, one -structure per interface. - - struct if_nameindex *if_nameindex(void); - -The end of the array of structures is indicated by a structure with an -if_index of 0 and an if_name of NULL. The function returns a NULL -pointer upon an error, and would set errno to the appropriate value. - -The memory used for this array of structures along with the interface -names pointed to by the if_name members is obtained dynamically. This -memory is freed by the next function. - - - -4.4 Free Memory - -The following function frees the dynamic memory that was allocated by -if_nameindex(). - - #include - - void if_freenameindex(struct if_nameindex *ptr); - -The argument to this function must be a pointer that was returned by -if_nameindex(). - -Currently net/if.h doesn't have prototype definitions for functions and -it is recommended that these definitions be defined in net/if.h as well -and the struct if_nameindex{}. - - - -5. Socket Options - -A number of new socket options are defined for IPv6. All of these new -options are at the IPPROTO_IPV6 level. That is, the "level" parameter -in the getsockopt() and setsockopt() calls is IPPROTO_IPV6 when using -these options. The constant name prefix IPV6_ is used in all of the new -socket options. This serves to clearly identify these options as -applying to IPv6. - -The declaration for IPPROTO_IPV6, the new IPv6 socket options, and -related constants defined in this section are obtained by including the -header . - - - - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 15] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - -5.1 Unicast Hop Limit - -A new setsockopt() option controls the hop limit used in outgoing -unicast IPv6 packets. The name of this option is IPV6_UNICAST_HOPS, and -it is used at the IPPROTO_IPV6 layer. The following example illustrates -how it is used: - - int hoplimit = 10; - - if (setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, - (char *) &hoplimit, sizeof(hoplimit)) == -1) - perror("setsockopt IPV6_UNICAST_HOPS"); - -When the IPV6_UNICAST_HOPS option is set with setsockopt(), the option -value given is used as the hop limit for all subsequent unicast packets -sent via that socket. If the option is not set, the system selects a -default value. The integer hop limit value (called x) is interpreted as -follows: - - x < -1: return an error of EINVAL - x == -1: use kernel default - 0 <= x <= 255: use x - x >= 256: return an error of EINVAL - -The IPV6_UNICAST_HOPS option may be used with getsockopt() to determine -the hop limit value that the system will use for subsequent unicast -packets sent via that socket. For example: - - int hoplimit; - size_t len = sizeof(hoplimit); - - if (getsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, - (char *) &hoplimit, &len) == -1) - perror("getsockopt IPV6_UNICAST_HOPS"); - else - printf("Using %d for hop limit.\n", hoplimit); - - - -5.2 Sending and Receiving Multicast Packets - -IPv6 applications may send UDP multicast packets by simply specifying an -IPv6 multicast address in the address argument of the sendto() function. - -Three socket options at the IPPROTO_IPV6 layer control some of the -parameters for sending multicast packets. Setting these options is not -required: applications may send multicast packets without using these -options. The setsockopt() options for controlling the sending of -multicast packets are summarized below. These three options can also be -used with getsockopt(). - - IPV6_MULTICAST_IF - - Set the interface to use for outgoing multicast packets. - The argument is the index of the interface to use. - - Argument type: unsigned int - - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 16] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - - IPV6_MULTICAST_HOPS - - Set the hop limit to use for outgoing multicast packets. - (Note a separate option - IPV6_UNICAST_HOPS - is - provided to set the hop limit to use for outgoing - unicast packets.) - - The interpretation of the argument is the same - as for the IPV6_UNICAST_HOPS option: - - x < -1: return an error of EINVAL - x == -1: use kernel default - 0 <= x <= 255: use x - x >= 256: return an error of EINVAL - - If IPV6_MULTICAST_HOPS is not set, the default is 1 - (same as IPv4 today) - - Argument type: int - - IPV6_MULTICAST_LOOP - - If a multicast datagram is sent to a group to which the sending host - itself belongs (on the outgoing interface), a copy of the datagram is - looped back by the IP layer for local delivery if this option is set to - 1. If this option is set to 0 a copy is not looped back. Other option - values return an error of EINVAL. - - If IPV6_MULTICAST_LOOP is not set, the default is 1 (loopback; same as - IPv4 today). - - Argument type: unsigned int - -The reception of multicast packets is controlled by the two setsockopt() -options summarized below. An error of EOPNOTSUPP is returned if these -two options are used with getsockopt(). - - IPV6_JOIN_GROUP - - Join a multicast group on a specified local interface. - If the interface index is specified as 0, - the kernel chooses the local interface. - For example, some kernels look up the multicast group - in the normal IPv6 routing table and using the resulting interface. - - Argument type: struct ipv6_mreq - - IPV6_LEAVE_GROUP - - Leave a multicast group on a specified interface. - - Argument type: struct ipv6_mreq - -The argument type of both of these options is the ipv6_mreq structure, -defined as a result of including the header; - - struct ipv6_mreq { - struct in6_addr ipv6mr_multiaddr; /* IPv6 multicast addr */ - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 17] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - - unsigned int ipv6mr_interface; /* interface index */ - }; - -Note that to receive multicast datagrams a process must join the -multicast group and bind the UDP port to which datagrams will be sent. -Some processes also bind the multicast group address to the socket, in -addition to the port, to prevent other datagrams destined to that same -port from being delivered to the socket. - - - -6. Library Functions - -New library functions are needed to perform a variety of operations with -IPv6 addresses. Functions are needed to lookup IPv6 addresses in the -Domain Name System (DNS). Both forward lookup (nodename-to-address -translation) and reverse lookup (address-to-nodename translation) need -to be supported. Functions are also needed to convert IPv6 addresses -between their binary and textual form. - -We note that the two existing functions, gethostbyname() and -gethostbyaddr(), are left as-is. New functions are defined to handle -both IPv4 and IPv6 addresses. - - - -6.1 Nodename-to-Address Translation - -The commonly used function gethostbyname() is inadequate for many -applications, first because it provides no way for the caller to specify -anything about the types of addresses desired (IPv4 only, IPv6 only, -IPv4-mapped IPv6 are OK, etc.), and second because many implementations -of this function are not thread safe. RFC 2133 defined a function named -gethostbyname2() but this function was also inadequate, first because -its use required setting a global option (RES_USE_INET6) when IPv6 -addresses were required, and second because a flag argument is needed to -provide the caller with additional control over the types of addresses -required. - -The following function is new and must be thread safe: - - #include - #include - - struct hostent *getipnodebyname(const char *name, int af, int flags - int *error_num); - -The name argument can be either a node name or a numeric address string -(i.e., a dotted-decimal IPv4 address or an IPv6 hex address). The af -argument specifies the address family, either AF_INET or AF_INET6. The -error_num value is returned to the caller, via a pointer, with the -appropriate error code in error_num, to support thread safe error code -returns. error_num will be set to one of the following values: - - HOST_NOT_FOUND - - No such host is known. - - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 18] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - - NO_ADDRESS - - The server recognised the request and the name but no address - is available. Another type of request to the name server for - the domain might return an answer. - - NO_RECOVERY - - An unexpected server failure occurred which cannot be recovered. - - TRY_AGAIN - - A temporary and possibly transient error occurred, such as a - failure of a server to respond. - - -The flags argument specifies the types of addresses that are searched -for, and the types of addresses that are returned. We note that a -special flags value of AI_DEFAULT (defined below) should handle most -applications. - -That is, porting simple applications to use IPv6 replaces the call - - hptr = gethostbyname(name); - -with - - hptr = getipnodebyname(name, AF_INET6, AI_DEFAULT, &error_num); - -and changes any subsequent error diagnosis code to use error_num instead -of externally declared variables, such as h_errno. - -Applications desiring finer control over the types of addresses searched -for and returned, can specify other combinations of the flags argument. - -A flags of 0 implies a strict interpretation of the af argument: - - - If flags is 0 and af is AF_INET, then the caller wants only IPv4 - addresses. A query is made for A records. If successful, the IPv4 - addresses are returned and the h_length member of the hostent - structure will be 4, else the function returns a NULL pointer. - - - If flags is 0 and if af is AF_INET6, then the caller wants only - IPv6 addresses. A query is made for AAAA records. If successful, - the IPv6 addresses are returned and the h_length member of the - hostent structure will be 16, else the function returns a NULL - pointer. - -Other constants can be logically-ORed into the flags argument, to modify -the behavior of the function. - - - If the AI_V4MAPPED flag is specified along with an af of - AF_INET6, then the caller will accept IPv4-mapped IPv6 - addresses. That is, if no AAAA records are found then a query - is made for A records and any found are returned as IPv4-mapped - IPv6 addresses (h_length will be 16). The AI_V4MAPPED flag is - ignored unless af equals AF_INET6. - - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 19] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - - - The AI_ALL flag is used in conjunction with the AI_V4MAPPED - flag, and is only used with the IPv6 address family. When AI_ALL - is logically or'd with AI_V4MAPPED flag then the caller wants - all addresses: IPv6 and IPv4-mapped IPv6. A query is first made - for AAAA records and if successful, the IPv6 addresses are returned. - Another query is then made for A records and any found are returned - as IPv4-mapped IPv6 addresses. h_length will be 16. Only if both - queries fail does the function return a NULL pointer. This flag is - ignored unless af equals AF_INET6. - - - The AI_ADDRCONFIG flag specifies that a query for AAAA records - should occur only if the node has at least one IPv6 source address - configured and a query for A records should occur only if the - node has at least one IPv4 source address configured. - - For example, if the node has no IPv6 source addresses configured, - and af equals AF_INET6, and the node name being looked up has both - AAAA and A records, then: - - (a) if only AI_ADDRCONFIG is specified, the function returns a - NULL pointer; - (b) if AI_ADDRCONFIG | AI_V4MAPPED is specified, the A records - are returned as IPv4-mapped IPv6 addresses; - -The special flags value of AI_DEFAULT is defined as - - #define AI_DEFAULT (AI_V4MAPPED | AI_ADDRCONFIG) - -We noted that the getipnodebyname() function must allow the name -argument to be either a node name or a literal address string (i.e., a -dotted-decimal IPv4 address or an IPv6 hex address). This saves -applications from having to call inet_pton() to handle literal address -strings. - -There are four scenarios based on the type of literal address string and -the value of the af argument. - -The two simple cases are: - -When name is a dotted-decimal IPv4 address and af equals AF_INET, or -when name is an IPv6 hex address and af equals AF_INET6. The members of -the returned hostent structure are: h_name points to a copy of the name -argument, h_aliases is a NULL pointer, h_addrtype is a copy of the af -argument, h_length is either 4 (for AF_INET) or 16 (for AF_INET6), -h_addr_list[0] is a pointer to the 4-byte or 16-byte binary address, and -h_addr_list[1] is a NULL pointer. - -When name is a dotted-decimal IPv4 address and af equals AF_INET6, and -flags equals AI_V4MAPPED, an IPv4-mapped IPv6 address is returned: -h_name points to an IPv6 hex address containing the IPv4-mapped IPv6 -address, h_aliases is a NULL pointer, h_addrtype is AF_INET6, h_length -is 16, h_addr_list[0] is a pointer to the 16-byte binary address, and -h_addr_list[1] is a NULL pointer. If AI_V4MAPPED is set (with or -without AI_ALL) return IPv4-mapped otherwise return NULL. - -It is an error when name is an IPv6 hex address and af equals AF_INET. -The function's return value is a NULL pointer and error_num equals -HOST_NOT_FOUND. - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 20] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - -6.2 Address-To-Nodename Translation - -The following function has the same arguments as the existing -gethostbyaddr() function, but adds an error number. - - #include - #include - - struct hostent *getipnodebyaddr(const void *src, size_t len, int af, - int *error_num); - -As with getipnodebyname(), getipnodebyaddr() must be thread safe. The -error_num value is returned to the caller with the appropriate error -code, to support thread safe error code returns. The following error -conditions may be returned for error_num: - - HOST_NOT_FOUND - - No such host is known. - - NO_ADDRESS - - The server recognized the request and the name but no address - is available. Another type of request to the name server for - the domain might return an answer. - - NO_RECOVERY - - An unexpected server failure occurred which cannot be recovered. - - TRY_AGAIN - - A temporary and possibly transient error occurred, such as a - failure of a server to respond. - - -One possible source of confusion is the handling of IPv4-mapped IPv6 -addresses and IPv4-compatible IPv6 addresses, but the following logic -should apply. - - 1. If af is AF_INET6, and if len equals 16, and if the IPv6 address - is an IPv4-mapped IPv6 address or an IPv4-compatible IPv6 address, - then skip over the first 12 bytes of the IPv6 address, set af to - AF_INET, and set len to 4. - - 2. If af is AF_INET, lookup the name for the given IPv4 address - (e.g., query for a PTR record in the in-addr.arpa domain). - - 3. If af is AF_INET6, lookup the name for the given IPv6 address - (e.g., query for a PTR record in the ip6.int domain). - - 4. If the function is returning success, then the single address that - is returned in the hostent structure is a copy of the first argument - to the function with the same address family that was passed as - an argument to this function. - -All four steps listed are performed, in order. Also note that the IPv6 -hex addresses "::" and "::1" MUST NOT be treated as IPv4-compatible - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 21] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - -addresses, and if the address is "::", HOST_NOT_FOUND MUST be returned -and a query of the address not performed. - -Also for the macro in section 6.7 IN6_IS_ADDR_V4COMPAT MUST return false -for "::" and "::1". - - - -6.3 Freeing memory for getipnodebyname and getipnodebyaddr - -The hostent structure does not change from its existing definition. -This structure, and the information pointed to by this structure, are -dynamically allocated by getipnodebyname and getipnodebyaddr. The -following function frees this memory: - - #include - - void freehostent(struct hostent *ptr); - - - -6.4 Protocol-Independent Nodename and Service Name Translation - -Nodename-to-address translation is done in a protocol-independent -fashion using the getaddrinfo() function that is taken from the -Institute of Electrical and Electronic Engineers (IEEE) POSIX 1003.1g -(Protocol Independent Interfaces) draft specification [3]. - -The official specification for this function will be the final POSIX -standard, with the following additional requirements: - - - getaddrinfo() (along with the getnameinfo() function described in - the next section) must be thread safe. - - - The AI_NUMERICHOST is new with this document. - - - All fields in socket address structures returned by getaddrinfo() - that are not filled in through an explicit argument (e.g., - sin6_flowinfo and sin_zero) must be set to 0. (This makes it easier - to compare socket address structures.) - - - getaddrinfo() must fill in the length field of a socket address structure - (e.g., sin6_len) on systems that support this field. - -We are providing this independent description of the function because -POSIX standards are not freely available (as are IETF documents). - - #include - #include - - int getaddrinfo(const char *nodename, const char *servname, - const struct addrinfo *hints, - struct addrinfo **res); - -The addrinfo structure is defined as a result of including the -header. - - struct addrinfo { - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 22] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - - int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */ - int ai_family; /* PF_xxx */ - int ai_socktype; /* SOCK_xxx */ - int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ - size_t ai_addrlen; /* length of ai_addr */ - char *ai_canonname; /* canonical name for nodename */ - struct sockaddr *ai_addr; /* binary address */ - struct addrinfo *ai_next; /* next structure in linked list */ - }; - -The return value from the function is 0 upon success or a nonzero error -code. The following names are the nonzero error codes from -getaddrinfo(), and are defined in : - - EAI_ADDRFAMILY address family for nodename not supported - EAI_AGAIN temporary failure in name resolution - EAI_BADFLAGS invalid value for ai_flags - EAI_FAIL non-recoverable failure in name resolution - EAI_FAMILY ai_family not supported - EAI_MEMORY memory allocation failure - EAI_NODATA no address associated with nodename - EAI_NONAME nodename nor servname provided, or not known - EAI_SERVICE servname not supported for ai_socktype - EAI_SOCKTYPE ai_socktype not supported - EAI_SYSTEM system error returned in errno - -The nodename and servname arguments are pointers to null-terminated -strings or NULL. One or both of these two arguments must be a non-NULL -pointer. In the normal client scenario, both the nodename and servname -are specified. In the normal server scenario, only the servname is -specified. A non-NULL nodename string can be either a node name or a -numeric host address string (i.e., a dotted-decimal IPv4 address or an -IPv6 hex address). A non-NULL servname string can be either a service -name or a decimal port number. - -The caller can optionally pass an addrinfo structure, pointed to by the -third argument, to provide hints concerning the type of socket that the -caller supports. In this hints structure all members other than -ai_flags, ai_family, ai_socktype, and ai_protocol must be zero or a NULL -pointer. A value of PF_UNSPEC for ai_family means the caller will -accept any protocol family. A value of 0 for ai_socktype means the -caller will accept any socket type. A value of 0 for ai_protocol means -the caller will accept any protocol. For example, if the caller handles -only TCP and not UDP, then the ai_socktype member of the hints structure -should be set to SOCK_STREAM when getaddrinfo() is called. If the -caller handles only IPv4 and not IPv6, then the ai_family member of the -hints structure should be set to PF_INET when getaddrinfo() is called. -If the third argument to getaddrinfo() is a NULL pointer, this is the -same as if the caller had filled in an addrinfo structure initialized to -zero with ai_family set to PF_UNSPEC. - -Upon successful return a pointer to a linked list of one or more -addrinfo structures is returned through the final argument. The caller -can process each addrinfo structure in this list by following the -ai_next pointer, until a NULL pointer is encountered. In each returned -addrinfo structure the three members ai_family, ai_socktype, and -ai_protocol are the corresponding arguments for a call to the socket() -function. In each addrinfo structure the ai_addr member points to a - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 23] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - -filled-in socket address structure whose length is specified by the -ai_addrlen member. - -If the AI_PASSIVE bit is set in the ai_flags member of the hints -structure, then the caller plans to use the returned socket address -structure in a call to bind(). In this case, if the nodename argument -is a NULL pointer, then the IP address portion of the socket address -structure will be set to INADDR_ANY for an IPv4 address or -IN6ADDR_ANY_INIT for an IPv6 address. - -If the AI_PASSIVE bit is not set in the ai_flags member of the hints -structure, then the returned socket address structure will be ready for -a call to connect() (for a connection-oriented protocol) or either -connect(), sendto(), or sendmsg() (for a connectionless protocol). In -this case, if the nodename argument is a NULL pointer, then the IP -address portion of the socket address structure will be set to the -loopback address. - -If the AI_CANONNAME bit is set in the ai_flags member of the hints -structure, then upon successful return the ai_canonname member of the -first addrinfo structure in the linked list will point to a null- -terminated string containing the canonical name of the specified -nodename. - -If the AI_NUMERICHOST bit is set in the ai_flags member of the hints -structure, then a non-NULL nodename string must be a numeric host -address string. Otherwise an error of EAI_NONAME is returned. This -flag prevents any type of name resolution service (e.g., the DNS) from -being called. - -All of the information returned by getaddrinfo() is dynamically -allocated: the addrinfo structures, and the socket address structures -and canonical node name strings pointed to by the addrinfo structures. -To return this information to the system the function freeaddrinfo() is -called: - - #include - #include - - void freeaddrinfo(struct addrinfo *ai); - -The addrinfo structure pointed to by the ai argument is freed, along -with any dynamic storage pointed to by the structure. This operation is -repeated until a NULL ai_next pointer is encountered. - -To aid applications in printing error messages based on the EAI_xxx -codes returned by getaddrinfo(), the following function is defined. - - #include - #include - - char *gai_strerror(int ecode); - -The argument is one of the EAI_xxx values defined earlier and the return -value points to a string describing the error. If the argument is not -one of the EAI_xxx values, the function still returns a pointer to a -string whose contents indicate an unknown error. - - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 24] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - -6.5 Socket Address Structure to Nodename and Service Name - -The POSIX 1003.1g specification includes no function to perform the -reverse conversion from getaddrinfo(): to look up a nodename and service -name, given the binary address and port. Therefore, we define the -following function: - - #include - #include - - int getnameinfo(const struct sockaddr *sa, socklen_t salen, - char *host, size_t hostlen, - char *serv, size_t servlen, - int flags); - -This function looks up an IP address and port number provided by the -caller in the DNS and system-specific database, and returns text strings -for both in buffers provided by the caller. The function indicates -successful completion by a zero return value; a non-zero return value -indicates failure. - -The first argument, sa, points to either a sockaddr_in structure (for -IPv4) or a sockaddr_in6 structure (for IPv6) that holds the IP address -and port number. The salen argument gives the length of the sockaddr_in -or sockaddr_in6 structure. - -The function returns the nodename associated with the IP address in the -buffer pointed to by the host argument. The caller provides the size of -this buffer via the hostlen argument. The service name associated with -the port number is returned in the buffer pointed to by serv, and the -servlen argument gives the length of this buffer. The caller specifies -not to return either string by providing a zero value for the hostlen or -servlen arguments. Otherwise, the caller must provide buffers large -enough to hold the nodename and the service name, including the -terminating null characters. - -Unfortunately most systems do not provide constants that specify the -maximum size of either a fully-qualified domain name or a service name. -Therefore to aid the application in allocating buffers for these two -returned strings the following constants are defined in : - - #define NI_MAXHOST 1025 - #define NI_MAXSERV 32 - -The first value is actually defined as the constant MAXDNAME in recent -versions of BIND's header (older versions of BIND -define this constant to be 256) and the second is a guess based on the -services listed in the current Assigned Numbers RFC. - -The final argument is a flag that changes the default actions of this -function. By default the fully-qualified domain name (FQDN) for the -host is looked up in the DNS and returned. If the flag bit NI_NOFQDN is -set, only the nodename portion of the FQDN is returned for local hosts. - -If the flag bit NI_NUMERICHOST is set, or if the host's name cannot be -located in the DNS, the numeric form of the host's address is returned -instead of its name (e.g., by calling inet_ntop() instead of -getipnodebyaddr()). If the flag bit NI_NAMEREQD is set, an error is - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 25] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - -returned if the host's name cannot be located in the DNS. - -If the flag bit NI_NUMERICSERV is set, the numeric form of the service -address is returned (e.g., its port number) instead of its name. The -two NI_NUMERICxxx flags are required to support the "-n" flag that many -commands provide. - -A fifth flag bit, NI_DGRAM, specifies that the service is a datagram -service, and causes getservbyport() to be called with a second argument -of "udp" instead of its default of "tcp". This is required for the few -ports (e.g. 512-514) that have different services for UDP and TCP. - -These NI_xxx flags are defined in along with the AI_xxx flags -already defined for getaddrinfo(). - - - -6.6 Address Conversion Functions - -The two functions inet_addr() and inet_ntoa() convert an IPv4 address -between binary and text form. IPv6 applications need similar functions. -The following two functions convert both IPv6 and IPv4 addresses: - - #include - #include - - int inet_pton(int af, const char *src, void *dst); - - const char *inet_ntop(int af, const void *src, - char *dst, size_t size); - -The inet_pton() function converts an address in its standard text -presentation form into its numeric binary form. The af argument -specifies the family of the address. Currently the AF_INET and AF_INET6 -address families are supported. The src argument points to the string -being passed in. The dst argument points to a buffer into which the -function stores the numeric address. The address is returned in network -byte order. Inet_pton() returns 1 if the conversion succeeds, 0 if the -input is not a valid IPv4 dotted-decimal string or a valid IPv6 address -string, or -1 with errno set to EAFNOSUPPORT if the af argument is -unknown. The calling application must ensure that the buffer referred -to by dst is large enough to hold the numeric address (e.g., 4 bytes for -AF_INET or 16 bytes for AF_INET6). - -If the af argument is AF_INET, the function accepts a string in the -standard IPv4 dotted-decimal form: - - ddd.ddd.ddd.ddd - -where ddd is a one to three digit decimal number between 0 and 255. -Note that many implementations of the existing inet_addr() and -inet_aton() functions accept nonstandard input: octal numbers, -hexadecimal numbers, and fewer than four numbers. inet_pton() does not -accept these formats. - -If the af argument is AF_INET6, then the function accepts a string in -one of the standard IPv6 text forms defined in Section 2.2 of the -addressing architecture specification [2]. - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 26] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - -The inet_ntop() function converts a numeric address into a text string -suitable for presentation. The af argument specifies the family of the -address. This can be AF_INET or AF_INET6. The src argument points to a -buffer holding an IPv4 address if the af argument is AF_INET, or an IPv6 -address if the af argument is AF_INET6, the address must be in network -byte order. The dst argument points to a buffer where the function will -store the resulting text string. The size argument specifies the size -of this buffer. The application must specify a non-NULL dst argument. -For IPv6 addresses, the buffer must be at least 46-octets. For IPv4 -addresses, the buffer must be at least 16-octets. In order to allow -applications to easily declare buffers of the proper size to store IPv4 -and IPv6 addresses in string form, the following two constants are -defined in : - - #define INET_ADDRSTRLEN 16 - #define INET6_ADDRSTRLEN 46 - -The inet_ntop() function returns a pointer to the buffer containing the -text string if the conversion succeeds, and NULL otherwise. Upon -failure, errno is set to EAFNOSUPPORT if the af argument is invalid or -ENOSPC if the size of the result buffer is inadequate. - - - -6.7 Address Testing Macros - -The following macros can be used to test for special IPv6 addresses. - - #include - - int IN6_IS_ADDR_UNSPECIFIED (const struct in6_addr *); - int IN6_IS_ADDR_LOOPBACK (const struct in6_addr *); - int IN6_IS_ADDR_MULTICAST (const struct in6_addr *); - int IN6_IS_ADDR_LINKLOCAL (const struct in6_addr *); - int IN6_IS_ADDR_SITELOCAL (const struct in6_addr *); - int IN6_IS_ADDR_V4MAPPED (const struct in6_addr *); - int IN6_IS_ADDR_V4COMPAT (const struct in6_addr *); - - int IN6_IS_ADDR_MC_NODELOCAL(const struct in6_addr *); - int IN6_IS_ADDR_MC_LINKLOCAL(const struct in6_addr *); - int IN6_IS_ADDR_MC_SITELOCAL(const struct in6_addr *); - int IN6_IS_ADDR_MC_ORGLOCAL (const struct in6_addr *); - int IN6_IS_ADDR_MC_GLOBAL (const struct in6_addr *); - -The first seven macros return true if the address is of the specified -type, or false otherwise. The last five test the scope of a multicast -address and return true if the address is a multicast address of the -specified scope or false if the address is either not a multicast -address or not of the specified scope. Note that IN6_IS_ADDR_LINKLOCAL -and IN6_IS_ADDR_SITELOCAL return true only for the two local-use IPv6 -unicast addresses. These two macros do not return true for IPv6 -multicast addresses of either link-local scope or site-local scope. - - - - - - - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 27] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - -7. Summary of New Definitions - -The following list summarizes the constants, structure, and extern -definitions discussed in this memo, sorted by header. - - IF_NAMESIZE - struct if_nameindex{}; - - AI_ADDRCONFIG - AI_DEFAULT - AI_ALL - AI_CANONNAME - AI_NUMERICHOST - AI_PASSIVE - AI_V4MAPPED - EAI_ADDRFAMILY - EAI_AGAIN - EAI_BADFLAGS - EAI_FAIL - EAI_FAMILY - EAI_MEMORY - EAI_NODATA - EAI_NONAME - EAI_SERVICE - EAI_SOCKTYPE - EAI_SYSTEM - NI_DGRAM - NI_MAXHOST - NI_MAXSERV - NI_NAMEREQD - NI_NOFQDN - NI_NUMERICHOST - NI_NUMERICSERV - struct addrinfo{}; - - IN6ADDR_ANY_INIT - IN6ADDR_LOOPBACK_INIT - INET6_ADDRSTRLEN - INET_ADDRSTRLEN - IPPROTO_IPV6 - IPV6_JOIN_GROUP - IPV6_LEAVE_GROUP - IPV6_MULTICAST_HOPS - IPV6_MULTICAST_IF - IPV6_MULTICAST_LOOP - IPV6_UNICAST_HOPS - SIN6_LEN - extern const struct in6_addr in6addr_any; - extern const struct in6_addr in6addr_loopback; - struct in6_addr{}; - struct ipv6_mreq{}; - struct sockaddr_in6{}; - - AF_INET6 - PF_INET6 - struct sockaddr_storage; - -The following list summarizes the function and macro prototypes - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 28] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - -discussed in this memo, sorted by header. - - int inet_pton(int, const char *, void *); - const char *inet_ntop(int, const void *, - char *, size_t); - - char *if_indextoname(unsigned int, char *); - unsigned int if_nametoindex(const char *); - void if_freenameindex(struct if_nameindex *); - struct if_nameindex *if_nameindex(void); - - int getaddrinfo(const char *, const char *, - const struct addrinfo *, - struct addrinfo **); - int getnameinfo(const struct sockaddr *, socklen_t, - char *, size_t, char *, size_t, int); - void freeaddrinfo(struct addrinfo *); - char *gai_strerror(int); - struct hostent *getipnodebyname(const char *, int, int, - int *); - struct hostent *getipnodebyaddr(const void *, size_t, int, - int *); - void freehostent(struct hostent *); - - int IN6_IS_ADDR_LINKLOCAL(const struct in6_addr *); - int IN6_IS_ADDR_LOOPBACK(const struct in6_addr *); - int IN6_IS_ADDR_MC_GLOBAL(const struct in6_addr *); - int IN6_IS_ADDR_MC_LINKLOCAL(const struct in6_addr *); - int IN6_IS_ADDR_MC_NODELOCAL(const struct in6_addr *); - int IN6_IS_ADDR_MC_ORGLOCAL(const struct in6_addr *); - int IN6_IS_ADDR_MC_SITELOCAL(const struct in6_addr *); - int IN6_IS_ADDR_MULTICAST(const struct in6_addr *); - int IN6_IS_ADDR_SITELOCAL(const struct in6_addr *); - int IN6_IS_ADDR_UNSPECIFIED(const struct in6_addr *); - int IN6_IS_ADDR_V4COMPAT(const struct in6_addr *); - int IN6_IS_ADDR_V4MAPPED(const struct in6_addr *); - - - - -8. Security Considerations - -IPv6 provides a number of new security mechanisms, many of which need to -be accessible to applications. Companion memos detailing the extensions -to the socket interfaces to support IPv6 security are being written. - - - -9. Year 2000 Considerations - -There are no issues for this draft concerning the Year 2000 issue -regarding the use of dates. - - - - - - - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 29] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - -Changes From RFC 2133 - -Changes made in the March 1998 Edition (-01 draft): - - Changed all "hostname" to "nodename" for consistency with other IPv6 - documents. - - Section 3.3: changed comment for sin6_flowinfo to be "traffic class & - flow info" and updated corresponding text description to current - definition of these two fields. - - Section 3.10 ("Portability Additions") is new. - - Section 6: a new paragraph was added reiterating that the existing - gethostbyname() and gethostbyaddr() are not changed. - - Section 6.1: change gethostbyname3() to getnodebyname(). Add - AI_DEFAULT to handle majority of applications. Renamed - AI_V6ADDRCONFIG to AI_ADDRCONFIG and define it for A records and IPv4 - addresses too. Defined exactly what getnodebyname() must return if - the name argument is a numeric address string. - - Section 6.2: change gethostbyaddr() to getnodebyaddr(). Reword items - 2 and 3 in the description of how to handle IPv4-mapped and IPv4- - compatible addresses to "lookup a name" for a given address, instead - of specifying what type of DNS query to issue. - - Section 6.3: added two more requirements to getaddrinfo(). - - Section 7: added the following constants to the list for : - AI_ADDRCONFIG, AI_ALL, and AI_V4MAPPED. Add union sockaddr_union and - SA_LEN to the lists for . - - Updated references. - -Changes made in the November 1997 Edition (-00 draft): - - The data types have been changed to conform with Draft 6.6 of the - Posix 1003.1g standard. - - Section 3.2: data type of s6_addr changed to "uint8_t". - - Section 3.3: data type of sin6_family changed to "sa_family_t". data - type of sin6_port changed to "in_port_t", data type of sin6_flowinfo - changed to "uint32_t". - - Section 3.4: same as Section 3.3, plus data type of sin6_len changed - to "uint8_t". - - Section 6.2: first argument of gethostbyaddr() changed from "const - char *" to "const void *" and second argument changed from "int" to - "size_t". - - Section 6.4: second argument of getnameinfo() changed from "size_t" - to "socklen_t". - - The wording was changed when new structures were defined, to be more - explicit as to which header must be included to define the structure: - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 30] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - - Section 3.2 (in6_addr{}), Section 3.3 (sockaddr_in6{}), Section 3.4 - (sockaddr_in6{}), Section 4.3 (if_nameindex{}), Section 5.3 - (ipv6_mreq{}), and Section 6.3 (addrinfo{}). - - Section 4: NET_RT_LIST changed to NET_RT_IFLIST. - - Section 5.1: The IPV6_ADDRFORM socket option was removed. - - Section 5.3: Added a note that an option value other than 0 or 1 for - IPV6_MULTICAST_LOOP returns an error. Added a note that - IPV6_MULTICAST_IF, IPV6_MULTICAST_HOPS, and IPV6_MULTICAST_LOOP can - also be used with getsockopt(), but IPV6_ADD_MEMBERSHIP and - IPV6_DROP_MEMBERSHIP cannot be used with getsockopt(). - - Section 6.1: Removed the description of gethostbyname2() and its - associated RES_USE_INET6 option, replacing it with gethostbyname3(). - - Section 6.2: Added requirement that gethostbyaddr() be thread safe. - Reworded step 4 to avoid using the RES_USE_INET6 option. - - Section 6.3: Added the requirement that getaddrinfo() and - getnameinfo() be thread safe. Added the AI_NUMERICHOST flag. - - Section 6.6: Added clarification about IN6_IS_ADDR_LINKLOCAL and - IN6_IS_ADDR_SITELOCAL macros. - -Changes made to the draft -01 specification Sept 98 - - Changed priority to traffic class in the spec. - - Added the need for scope identification in section 2.1. - - Added sin6_scope_id to struct sockaddr_in6 in sections 3.3 and 3.4. - - Changed 3.10 to use generic storage structure to support holding IPv6 - addresses and removed the SA_LEN macro. - - Distinguished between invalid input parameters and system failures - for Interface Identification in Section 4.1 and 4.2. - - Added defaults for multicast operations in section 5.2 and changed - the names from ADD to JOIN and DROP to LEAVE to be consistent with - IPv6 multicast terminology. - - Changed getnodebyname to getipnodebyname, getnodebyaddr to - getipnodebyaddr, and added MT safe error code to function parameters - in section 6. - - Moved freehostent to its own sub-section after getipnodebyaddr now - 6.3 (so this bumps all remaining sections in section 6. - - Clarified the use of AI_ALL and AI_V4MAPPED that these are dependent - on the AF parameter and must be used as a conjunction in section 6.1. - - Removed the restriction that literal addresses cannot be used with a - flags argument in section 6.1. - - Added Year 2000 Section to the draft - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 31] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - - Deleted Reference to the following because the attached is deleted from - the ID directory and has expired. But the logic from the aforementioned - draft still applies, so that was kept in Section 6.2 bullets after 3rd - paragraph. - [7] P. Vixie, "Reverse Name Lookups of Encapsulated IPv4 Addresses - in IPv6", Internet-Draft, , - May 1996. - - Deleted the following reference as it is no longer referenced. - And the draft has expired. - [3] D. McDonald, "A Simple IP Security API Extension to BSD Sockets", - Internet-Draft, , - March 1997. - - Deleted the following reference as it is no longer referenced. - [4] C. Metz, "Network Security API for Sockets", - Internet-Draft, , - January 1998. - - Update current references to current status. - - Added alignment notes for in6_addr and sin6_addr. - - Clarified further that AI_V4MAPPED must be used with a dotted IPv4 - literal address for getipnodebyname(), when address family is - AF_INET6. - - Added text to clarify "::" and "::1" when used by getipnodebyaddr(). - - - - -Acknowledgments - -Thanks to the many people who made suggestions and provided feedback to -this document, including: Werner Almesberger, Ran Atkinson, Fred Baker, -Dave Borman, Andrew Cherenson, Alex Conta, Alan Cox, Steve Deering, -Richard Draves, Francis Dupont, Robert Elz, Marc Hasson, Tom Herbert, -Bob Hinden, Wan-Yen Hsu, Christian Huitema, Koji Imada, Markus Jork, Ron -Lee, Alan Lloyd, Charles Lynn, Dan McDonald, Dave Mitton, Thomas Narten, -Josh Osborne, Craig Partridge, Jean-Luc Richier, Erik Scoredos, Keith -Sklower, Matt Thomas, Harvey Thompson, Dean D. Throop, Karen Tracey, -Glenn Trewitt, Paul Vixie, David Waitzman, Carl Williams, and Kazu -Yamamoto, - -The getaddrinfo() and getnameinfo() functions are taken from an earlier -Internet Draft by Keith Sklower. As noted in that draft, William Durst, -Steven Wise, Michael Karels, and Eric Allman provided many useful -discussions on the subject of protocol-independent name-to-address -translation, and reviewed early versions of Keith Sklower's original -proposal. Eric Allman implemented the first prototype of getaddrinfo(). -The observation that specifying the pair of name and service would -suffice for connecting to a service independent of protocol details was -made by Marshall Rose in a proposal to X/Open for a "Uniform Network -Interface". - -Craig Metz, Jack McCann, Erik Nordmark, Tim Hartrick, and Mukesh Kacker -made many contributions to this document. Ramesh Govindan made a number - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 32] - - -INTERNET-DRAFT draft-ietf-ipngwg-bsd-api-new-06.txt January 1999 - - -of contributions and co-authored an earlier version of this memo. - - - -References - - [1] S. Deering, R. Hinden, "Internet Protocol, Version 6 (IPv6) - Specification", RFC 2460 Draft Standard. - - [2] R. Hinden, S. Deering, "IP Version 6 Addressing Architecture", - RFC 2373, July 1998 Draft Standard. - - [3] IEEE, "Protocol Independent Interfaces", - IEEE Std 1003.1g, DRAFT 6.6, - March 1997. - - [4] W. Stevens, M. Thomas, "Advanced Sockets API for IPv6", - RFC 2292, February 1998. - - - - -Authors' Addresses - -Robert E. Gilligan -FreeGate Corporation -1208 E. Arques Ave. -Sunnyvale, CA 94086 -Phone: +1 408 617 1004 -Email: gilligan@freegate.net - -Susan Thomson -Bell Communications Research -MRE 2P-343, 445 South Street -Morristown, NJ 07960 -Telephone: +1 201 829 4514 -Email: set@thumper.bellcore.com - -Jim Bound -Compaq Computer Corporation -110 Spitbrook Road ZK3-3/U14 -Nashua, NH 03062-2698 -Phone: +1 603 884 0400 -Email: bound@zk3.dec.com - -W. Richard Stevens -1202 E. Paseo del Zorro -Tucson, AZ 85718-2826 -Phone: +1 520 297 9416 -Email: rstevens@kohala.com - - - - - - - - - - -draft-ietf-ipng-bsd-api-new-06.txt Expires June 1999 [Page 33] diff --git a/doc/rfc/rfc2553.txt b/doc/rfc/rfc2553.txt new file mode 100644 index 0000000000..6989bf3045 --- /dev/null +++ b/doc/rfc/rfc2553.txt @@ -0,0 +1,2299 @@ + + + + + + +Network Working Group R. Gilligan +Request for Comments: 2553 FreeGate +Obsoletes: 2133 S. Thomson +Category: Informational Bellcore + J. Bound + Compaq + W. Stevens + Consultant + March 1999 + + + Basic Socket Interface Extensions for IPv6 + +Status of this Memo + + This memo provides information for the Internet community. It does + not specify an Internet standard of any kind. Distribution of this + memo is unlimited. + +Copyright Notice + + Copyright (C) The Internet Society (1999). All Rights Reserved. + +Abstract + + The de facto standard application program interface (API) for TCP/IP + applications is the "sockets" interface. Although this API was + developed for Unix in the early 1980s it has also been implemented on + a wide variety of non-Unix systems. TCP/IP applications written + using the sockets API have in the past enjoyed a high degree of + portability and we would like the same portability with IPv6 + applications. But changes are required to the sockets API to support + IPv6 and this memo describes these changes. These include a new + socket address structure to carry IPv6 addresses, new address + conversion functions, and some new socket options. These extensions + are designed to provide access to the basic IPv6 features required by + TCP and UDP applications, including multicasting, while introducing a + minimum of change into the system and providing complete + compatibility for existing IPv4 applications. Additional extensions + for advanced IPv6 features (raw sockets and access to the IPv6 + extension headers) are defined in another document [4]. + + + + + + + + + + +Gilligan, et. al. Informational [Page 1] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + +Table of Contents + + 1. Introduction.................................................3 + 2. Design Considerations........................................3 + 2.1 What Needs to be Changed....................................4 + 2.2 Data Types..................................................5 + 2.3 Headers.....................................................5 + 2.4 Structures..................................................5 + 3. Socket Interface.............................................6 + 3.1 IPv6 Address Family and Protocol Family.....................6 + 3.2 IPv6 Address Structure......................................6 + 3.3 Socket Address Structure for 4.3BSD-Based Systems...........7 + 3.4 Socket Address Structure for 4.4BSD-Based Systems...........8 + 3.5 The Socket Functions........................................9 + 3.6 Compatibility with IPv4 Applications.......................10 + 3.7 Compatibility with IPv4 Nodes..............................10 + 3.8 IPv6 Wildcard Address......................................11 + 3.9 IPv6 Loopback Address......................................12 + 3.10 Portability Additions.....................................13 + 4. Interface Identification....................................16 + 4.1 Name-to-Index..............................................16 + 4.2 Index-to-Name..............................................17 + 4.3 Return All Interface Names and Indexes.....................17 + 4.4 Free Memory................................................18 + 5. Socket Options..............................................18 + 5.1 Unicast Hop Limit..........................................18 + 5.2 Sending and Receiving Multicast Packets....................19 + 6. Library Functions...........................................21 + 6.1 Nodename-to-Address Translation............................21 + 6.2 Address-To-Nodename Translation............................24 + 6.3 Freeing memory for getipnodebyname and getipnodebyaddr.....26 + 6.4 Protocol-Independent Nodename and Service Name Translation.26 + 6.5 Socket Address Structure to Nodename and Service Name......29 + 6.6 Address Conversion Functions...............................31 + 6.7 Address Testing Macros.....................................32 + 7. Summary of New Definitions..................................33 + 8. Security Considerations.....................................35 + 9. Year 2000 Considerations....................................35 + Changes From RFC 2133..........................................35 + Acknowledgments................................................38 + References.....................................................39 + Authors' Addresses.............................................40 + Full Copyright Statement.......................................41 + + + + + + + + +Gilligan, et. al. Informational [Page 2] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + +1. Introduction + + While IPv4 addresses are 32 bits long, IPv6 interfaces are identified + by 128-bit addresses. The socket interface makes the size of an IP + address quite visible to an application; virtually all TCP/IP + applications for BSD-based systems have knowledge of the size of an + IP address. Those parts of the API that expose the addresses must be + changed to accommodate the larger IPv6 address size. IPv6 also + introduces new features (e.g., traffic class and flowlabel), some of + which must be made visible to applications via the API. This memo + defines a set of extensions to the socket interface to support the + larger address size and new features of IPv6. + +2. Design Considerations + + There are a number of important considerations in designing changes + to this well-worn API: + + - The API changes should provide both source and binary + compatibility for programs written to the original API. That + is, existing program binaries should continue to operate when + run on a system supporting the new API. In addition, existing + applications that are re-compiled and run on a system supporting + the new API should continue to operate. Simply put, the API + changes for IPv6 should not break existing programs. An + additonal mechanism for implementations to verify this is to + verify the new symbols are protected by Feature Test Macros as + described in IEEE Std 1003.1. (Such Feature Test Macros are not + defined by this RFC.) + + - The changes to the API should be as small as possible in order + to simplify the task of converting existing IPv4 applications to + IPv6. + + - Where possible, applications should be able to use this API to + interoperate with both IPv6 and IPv4 hosts. Applications should + not need to know which type of host they are communicating with. + + - IPv6 addresses carried in data structures should be 64-bit + aligned. This is necessary in order to obtain optimum + performance on 64-bit machine architectures. + + Because of the importance of providing IPv4 compatibility in the API, + these extensions are explicitly designed to operate on machines that + provide complete support for both IPv4 and IPv6. A subset of this + API could probably be designed for operation on systems that support + only IPv6. However, this is not addressed in this memo. + + + + +Gilligan, et. al. Informational [Page 3] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + +2.1 What Needs to be Changed + + The socket interface API consists of a few distinct components: + + - Core socket functions. + + - Address data structures. + + - Name-to-address translation functions. + + - Address conversion functions. + + The core socket functions -- those functions that deal with such + things as setting up and tearing down TCP connections, and sending + and receiving UDP packets -- were designed to be transport + independent. Where protocol addresses are passed as function + arguments, they are carried via opaque pointers. A protocol-specific + address data structure is defined for each protocol that the socket + functions support. Applications must cast pointers to these + protocol-specific address structures into pointers to the generic + "sockaddr" address structure when using the socket functions. These + functions need not change for IPv6, but a new IPv6-specific address + data structure is needed. + + The "sockaddr_in" structure is the protocol-specific data structure + for IPv4. This data structure actually includes 8-octets of unused + space, and it is tempting to try to use this space to adapt the + sockaddr_in structure to IPv6. Unfortunately, the sockaddr_in + structure is not large enough to hold the 16-octet IPv6 address as + well as the other information (address family and port number) that + is needed. So a new address data structure must be defined for IPv6. + + IPv6 addresses are scoped [2] so they could be link-local, site, + organization, global, or other scopes at this time undefined. To + support applications that want to be able to identify a set of + interfaces for a specific scope, the IPv6 sockaddr_in structure must + support a field that can be used by an implementation to identify a + set of interfaces identifying the scope for an IPv6 address. + + The name-to-address translation functions in the socket interface are + gethostbyname() and gethostbyaddr(). These are left as is and new + functions are defined to support IPv4 and IPv6. Additionally, the + POSIX 1003.g draft [3] specifies a new nodename-to-address + translation function which is protocol independent. This function + can also be used with IPv4 and IPv6. + + + + + + +Gilligan, et. al. Informational [Page 4] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + The address conversion functions -- inet_ntoa() and inet_addr() -- + convert IPv4 addresses between binary and printable form. These + functions are quite specific to 32-bit IPv4 addresses. We have + designed two analogous functions that convert both IPv4 and IPv6 + addresses, and carry an address type parameter so that they can be + extended to other protocol families as well. + + Finally, a few miscellaneous features are needed to support IPv6. + New interfaces are needed to support the IPv6 traffic class, flow + label, and hop limit header fields. New socket options are needed to + control the sending and receiving of IPv6 multicast packets. + + The socket interface will be enhanced in the future to provide access + to other IPv6 features. These extensions are described in [4]. + +2.2 Data Types + + The data types of the structure elements given in this memo are + intended to be examples, not absolute requirements. Whenever + possible, data types from Draft 6.6 (March 1997) of POSIX 1003.1g are + used: uintN_t means an unsigned integer of exactly N bits (e.g., + uint16_t). We also assume the argument data types from 1003.1g when + possible (e.g., the final argument to setsockopt() is a size_t + value). Whenever buffer sizes are specified, the POSIX 1003.1 size_t + data type is used (e.g., the two length arguments to getnameinfo()). + +2.3 Headers + + When function prototypes and structures are shown we show the headers + that must be #included to cause that item to be defined. + +2.4 Structures + + When structures are described the members shown are the ones that + must appear in an implementation. Additional, nonstandard members + may also be defined by an implementation. As an additional + precaution nonstandard members could be verified by Feature Test + Macros as described in IEEE Std 1003.1. (Such Feature Test Macros + are not defined by this RFC.) + + The ordering shown for the members of a structure is the recommended + ordering, given alignment considerations of multibyte members, but an + implementation may order the members differently. + + + + + + + + +Gilligan, et. al. Informational [Page 5] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + +3. Socket Interface + + This section specifies the socket interface changes for IPv6. + +3.1 IPv6 Address Family and Protocol Family + + A new address family name, AF_INET6, is defined in . + The AF_INET6 definition distinguishes between the original + sockaddr_in address data structure, and the new sockaddr_in6 data + structure. + + A new protocol family name, PF_INET6, is defined in . + Like most of the other protocol family names, this will usually be + defined to have the same value as the corresponding address family + name: + + #define PF_INET6 AF_INET6 + + The PF_INET6 is used in the first argument to the socket() function + to indicate that an IPv6 socket is being created. + +3.2 IPv6 Address Structure + + A new in6_addr structure holds a single IPv6 address and is defined + as a result of including : + + struct in6_addr { + uint8_t s6_addr[16]; /* IPv6 address */ + }; + + This data structure contains an array of sixteen 8-bit elements, + which make up one 128-bit IPv6 address. The IPv6 address is stored + in network byte order. + + The structure in6_addr above is usually implemented with an embedded + union with extra fields that force the desired alignment level in a + manner similar to BSD implementations of "struct in_addr". Those + additional implementation details are omitted here for simplicity. + + An example is as follows: + + + + + + + + + + + +Gilligan, et. al. Informational [Page 6] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + struct in6_addr { + union { + uint8_t _S6_u8[16]; + uint32_t _S6_u32[4]; + uint64_t _S6_u64[2]; + } _S6_un; + }; + #define s6_addr _S6_un._S6_u8 + +3.3 Socket Address Structure for 4.3BSD-Based Systems + + In the socket interface, a different protocol-specific data structure + is defined to carry the addresses for each protocol suite. Each + protocol- specific data structure is designed so it can be cast into a + protocol- independent data structure -- the "sockaddr" structure. + Each has a "family" field that overlays the "sa_family" of the + sockaddr data structure. This field identifies the type of the data + structure. + + The sockaddr_in structure is the protocol-specific address data + structure for IPv4. It is used to pass addresses between applications + and the system in the socket functions. The following sockaddr_in6 + structure holds IPv6 addresses and is defined as a result of including + the header: + +struct sockaddr_in6 { + sa_family_t sin6_family; /* AF_INET6 */ + in_port_t sin6_port; /* transport layer port # */ + uint32_t sin6_flowinfo; /* IPv6 traffic class & flow info */ + struct in6_addr sin6_addr; /* IPv6 address */ + uint32_t sin6_scope_id; /* set of interfaces for a scope */ +}; + + This structure is designed to be compatible with the sockaddr data + structure used in the 4.3BSD release. + + The sin6_family field identifies this as a sockaddr_in6 structure. + This field overlays the sa_family field when the buffer is cast to a + sockaddr data structure. The value of this field must be AF_INET6. + + The sin6_port field contains the 16-bit UDP or TCP port number. This + field is used in the same way as the sin_port field of the + sockaddr_in structure. The port number is stored in network byte + order. + + + + + + + +Gilligan, et. al. Informational [Page 7] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + The sin6_flowinfo field is a 32-bit field that contains two pieces of + information: the traffic class and the flow label. The contents and + interpretation of this member is specified in [1]. The sin6_flowinfo + field SHOULD be set to zero by an implementation prior to using the + sockaddr_in6 structure by an application on receive operations. + + The sin6_addr field is a single in6_addr structure (defined in the + previous section). This field holds one 128-bit IPv6 address. The + address is stored in network byte order. + + The ordering of elements in this structure is specifically designed + so that when sin6_addr field is aligned on a 64-bit boundary, the + start of the structure will also be aligned on a 64-bit boundary. + This is done for optimum performance on 64-bit architectures. + + The sin6_scope_id field is a 32-bit integer that identifies a set of + interfaces as appropriate for the scope of the address carried in the + sin6_addr field. For a link scope sin6_addr sin6_scope_id would be + an interface index. For a site scope sin6_addr, sin6_scope_id would + be a site identifier. The mapping of sin6_scope_id to an interface + or set of interfaces is left to implementation and future + specifications on the subject of site identifiers. + + Notice that the sockaddr_in6 structure will normally be larger than + the generic sockaddr structure. On many existing implementations the + sizeof(struct sockaddr_in) equals sizeof(struct sockaddr), with both + being 16 bytes. Any existing code that makes this assumption needs + to be examined carefully when converting to IPv6. + +3.4 Socket Address Structure for 4.4BSD-Based Systems + + The 4.4BSD release includes a small, but incompatible change to the + socket interface. The "sa_family" field of the sockaddr data + structure was changed from a 16-bit value to an 8-bit value, and the + space saved used to hold a length field, named "sa_len". The + sockaddr_in6 data structure given in the previous section cannot be + correctly cast into the newer sockaddr data structure. For this + reason, the following alternative IPv6 address data structure is + provided to be used on systems based on 4.4BSD. It is defined as a + result of including the header. + + + + + + + + + + + +Gilligan, et. al. Informational [Page 8] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + +struct sockaddr_in6 { + uint8_t sin6_len; /* length of this struct */ + sa_family_t sin6_family; /* AF_INET6 */ + in_port_t sin6_port; /* transport layer port # */ + uint32_t sin6_flowinfo; /* IPv6 flow information */ + struct in6_addr sin6_addr; /* IPv6 address */ + uint32_t sin6_scope_id; /* set of interfaces for a scope */ +}; + + The only differences between this data structure and the 4.3BSD + variant are the inclusion of the length field, and the change of the + family field to a 8-bit data type. The definitions of all the other + fields are identical to the structure defined in the previous + section. + + Systems that provide this version of the sockaddr_in6 data structure + must also declare SIN6_LEN as a result of including the + header. This macro allows applications to determine + whether they are being built on a system that supports the 4.3BSD or + 4.4BSD variants of the data structure. + +3.5 The Socket Functions + + Applications call the socket() function to create a socket descriptor + that represents a communication endpoint. The arguments to the + socket() function tell the system which protocol to use, and what + format address structure will be used in subsequent functions. For + example, to create an IPv4/TCP socket, applications make the call: + + s = socket(PF_INET, SOCK_STREAM, 0); + + To create an IPv4/UDP socket, applications make the call: + + s = socket(PF_INET, SOCK_DGRAM, 0); + + Applications may create IPv6/TCP and IPv6/UDP sockets by simply using + the constant PF_INET6 instead of PF_INET in the first argument. For + example, to create an IPv6/TCP socket, applications make the call: + + s = socket(PF_INET6, SOCK_STREAM, 0); + + To create an IPv6/UDP socket, applications make the call: + + s = socket(PF_INET6, SOCK_DGRAM, 0); + + + + + + + +Gilligan, et. al. Informational [Page 9] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + Once the application has created a PF_INET6 socket, it must use the + sockaddr_in6 address structure when passing addresses in to the + system. The functions that the application uses to pass addresses + into the system are: + + bind() + connect() + sendmsg() + sendto() + + The system will use the sockaddr_in6 address structure to return + addresses to applications that are using PF_INET6 sockets. The + functions that return an address from the system to an application + are: + + accept() + recvfrom() + recvmsg() + getpeername() + getsockname() + + No changes to the syntax of the socket functions are needed to + support IPv6, since all of the "address carrying" functions use an + opaque address pointer, and carry an address length as a function + argument. + +3.6 Compatibility with IPv4 Applications + + In order to support the large base of applications using the original + API, system implementations must provide complete source and binary + compatibility with the original API. This means that systems must + continue to support PF_INET sockets and the sockaddr_in address + structure. Applications must be able to create IPv4/TCP and IPv4/UDP + sockets using the PF_INET constant in the socket() function, as + described in the previous section. Applications should be able to + hold a combination of IPv4/TCP, IPv4/UDP, IPv6/TCP and IPv6/UDP + sockets simultaneously within the same process. + + Applications using the original API should continue to operate as + they did on systems supporting only IPv4. That is, they should + continue to interoperate with IPv4 nodes. + +3.7 Compatibility with IPv4 Nodes + + The API also provides a different type of compatibility: the ability + for IPv6 applications to interoperate with IPv4 applications. This + feature uses the IPv4-mapped IPv6 address format defined in the IPv6 + addressing architecture specification [2]. This address format + + + +Gilligan, et. al. Informational [Page 10] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + allows the IPv4 address of an IPv4 node to be represented as an IPv6 + address. The IPv4 address is encoded into the low-order 32 bits of + the IPv6 address, and the high-order 96 bits hold the fixed prefix + 0:0:0:0:0:FFFF. IPv4- mapped addresses are written as follows: + + ::FFFF: + + These addresses can be generated automatically by the + getipnodebyname() function when the specified host has only IPv4 + addresses (as described in Section 6.1). + + Applications may use PF_INET6 sockets to open TCP connections to IPv4 + nodes, or send UDP packets to IPv4 nodes, by simply encoding the + destination's IPv4 address as an IPv4-mapped IPv6 address, and + passing that address, within a sockaddr_in6 structure, in the + connect() or sendto() call. When applications use PF_INET6 sockets + to accept TCP connections from IPv4 nodes, or receive UDP packets + from IPv4 nodes, the system returns the peer's address to the + application in the accept(), recvfrom(), or getpeername() call using + a sockaddr_in6 structure encoded this way. + + Few applications will likely need to know which type of node they are + interoperating with. However, for those applications that do need to + know, the IN6_IS_ADDR_V4MAPPED() macro, defined in Section 6.7, is + provided. + +3.8 IPv6 Wildcard Address + + While the bind() function allows applications to select the source IP + address of UDP packets and TCP connections, applications often want + the system to select the source address for them. With IPv4, one + specifies the address as the symbolic constant INADDR_ANY (called the + "wildcard" address) in the bind() call, or simply omits the bind() + entirely. + + Since the IPv6 address type is a structure (struct in6_addr), a + symbolic constant can be used to initialize an IPv6 address variable, + but cannot be used in an assignment. Therefore systems provide the + IPv6 wildcard address in two forms. + + The first version is a global variable named "in6addr_any" that is an + in6_addr structure. The extern declaration for this variable is + defined in : + + extern const struct in6_addr in6addr_any; + + + + + + +Gilligan, et. al. Informational [Page 11] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + Applications use in6addr_any similarly to the way they use INADDR_ANY + in IPv4. For example, to bind a socket to port number 23, but let + the system select the source address, an application could use the + following code: + + struct sockaddr_in6 sin6; + . . . + sin6.sin6_family = AF_INET6; + sin6.sin6_flowinfo = 0; + sin6.sin6_port = htons(23); + sin6.sin6_addr = in6addr_any; /* structure assignment */ + . . . + if (bind(s, (struct sockaddr *) &sin6, sizeof(sin6)) == -1) + . . . + + The other version is a symbolic constant named IN6ADDR_ANY_INIT and + is defined in . This constant can be used to + initialize an in6_addr structure: + + struct in6_addr anyaddr = IN6ADDR_ANY_INIT; + + Note that this constant can be used ONLY at declaration time. It can + not be used to assign a previously declared in6_addr structure. For + example, the following code will not work: + + /* This is the WRONG way to assign an unspecified address */ + struct sockaddr_in6 sin6; + . . . + sin6.sin6_addr = IN6ADDR_ANY_INIT; /* will NOT compile */ + + Be aware that the IPv4 INADDR_xxx constants are all defined in host + byte order but the IPv6 IN6ADDR_xxx constants and the IPv6 + in6addr_xxx externals are defined in network byte order. + +3.9 IPv6 Loopback Address + + Applications may need to send UDP packets to, or originate TCP + connections to, services residing on the local node. In IPv4, they + can do this by using the constant IPv4 address INADDR_LOOPBACK in + their connect(), sendto(), or sendmsg() call. + + IPv6 also provides a loopback address to contact local TCP and UDP + services. Like the unspecified address, the IPv6 loopback address is + provided in two forms -- a global variable and a symbolic constant. + + + + + + + +Gilligan, et. al. Informational [Page 12] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + The global variable is an in6_addr structure named + "in6addr_loopback." The extern declaration for this variable is + defined in : + + extern const struct in6_addr in6addr_loopback; + + Applications use in6addr_loopback as they would use INADDR_LOOPBACK + in IPv4 applications (but beware of the byte ordering difference + mentioned at the end of the previous section). For example, to open + a TCP connection to the local telnet server, an application could use + the following code: + + struct sockaddr_in6 sin6; + . . . + sin6.sin6_family = AF_INET6; + sin6.sin6_flowinfo = 0; + sin6.sin6_port = htons(23); + sin6.sin6_addr = in6addr_loopback; /* structure assignment */ + . . . + if (connect(s, (struct sockaddr *) &sin6, sizeof(sin6)) == -1) + . . . + + The symbolic constant is named IN6ADDR_LOOPBACK_INIT and is defined + in . It can be used at declaration time ONLY; for + example: + + struct in6_addr loopbackaddr = IN6ADDR_LOOPBACK_INIT; + + Like IN6ADDR_ANY_INIT, this constant cannot be used in an assignment + to a previously declared IPv6 address variable. + +3.10 Portability Additions + + One simple addition to the sockets API that can help application + writers is the "struct sockaddr_storage". This data structure can + simplify writing code portable across multiple address families and + platforms. This data structure is designed with the following goals. + + - It has a large enough implementation specific maximum size to + store the desired set of protocol specific socket address data + structures. Specifically, it is at least large enough to + accommodate sockaddr_in and sockaddr_in6 and possibly other + protocol specific socket addresses too. + - It is aligned at an appropriate boundary so protocol specific + socket address data structure pointers can be cast to it and + access their fields without alignment problems. (e.g. pointers + to sockaddr_in6 and/or sockaddr_in can be cast to it and access + fields without alignment problems). + + + +Gilligan, et. al. Informational [Page 13] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + - It has the initial field(s) isomorphic to the fields of the + "struct sockaddr" data structure on that implementation which + can be used as a discriminants for deriving the protocol in use. + These initial field(s) would on most implementations either be a + single field of type "sa_family_t" (isomorphic to sa_family + field, 16 bits) or two fields of type uint8_t and sa_family_t + respectively, (isomorphic to sa_len and sa_family_t, 8 bits + each). + + An example implementation design of such a data structure would be as + follows. + +/* + * Desired design of maximum size and alignment + */ +#define _SS_MAXSIZE 128 /* Implementation specific max size */ +#define _SS_ALIGNSIZE (sizeof (int64_t)) + /* Implementation specific desired alignment */ +/* + * Definitions used for sockaddr_storage structure paddings design. + */ +#define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof (sa_family_t)) +#define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof (sa_family_t)+ + _SS_PAD1SIZE + _SS_ALIGNSIZE)) +struct sockaddr_storage { + sa_family_t __ss_family; /* address family */ + /* Following fields are implementation specific */ + char __ss_pad1[_SS_PAD1SIZE]; + /* 6 byte pad, this is to make implementation + /* specific pad up to alignment field that */ + /* follows explicit in the data structure */ + int64_t __ss_align; /* field to force desired structure */ + /* storage alignment */ + char __ss_pad2[_SS_PAD2SIZE]; + /* 112 byte pad to achieve desired size, */ + /* _SS_MAXSIZE value minus size of ss_family */ + /* __ss_pad1, __ss_align fields is 112 */ +}; + + On implementations where sockaddr data structure includes a "sa_len", + field this data structure would look like this: + +/* + * Definitions used for sockaddr_storage structure paddings design. + */ +#define _SS_PAD1SIZE (_SS_ALIGNSIZE - + (sizeof (uint8_t) + sizeof (sa_family_t)) +#define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof (sa_family_t)+ + + + +Gilligan, et. al. Informational [Page 14] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + _SS_PAD1SIZE + _SS_ALIGNSIZE)) +struct sockaddr_storage { + uint8_t __ss_len; /* address length */ + sa_family_t __ss_family; /* address family */ + /* Following fields are implementation specific */ + char __ss_pad1[_SS_PAD1SIZE]; + /* 6 byte pad, this is to make implementation + /* specific pad up to alignment field that */ + /* follows explicit in the data structure */ + int64_t __ss_align; /* field to force desired structure */ + /* storage alignment */ + char __ss_pad2[_SS_PAD2SIZE]; + /* 112 byte pad to achieve desired size, */ + /* _SS_MAXSIZE value minus size of ss_len, */ + /* __ss_family, __ss_pad1, __ss_align fields is 112 */ +}; + + The above example implementation illustrates a data structure which + will align on a 64 bit boundary. An implementation specific field + "__ss_align" along "__ss_pad1" is used to force a 64-bit alignment + which covers proper alignment good enough for needs of sockaddr_in6 + (IPv6), sockaddr_in (IPv4) address data structures. The size of + padding fields __ss_pad1 depends on the chosen alignment boundary. + The size of padding field __ss_pad2 depends on the value of overall + size chosen for the total size of the structure. This size and + alignment are represented in the above example by implementation + specific (not required) constants _SS_MAXSIZE (chosen value 128) and + _SS_ALIGNMENT (with chosen value 8). Constants _SS_PAD1SIZE (derived + value 6) and _SS_PAD2SIZE (derived value 112) are also for + illustration and not required. The implementation specific + definitions and structure field names above start with an underscore + to denote implementation private namespace. Portable code is not + expected to access or reference those fields or constants. + + The sockaddr_storage structure solves the problem of declaring + storage for automatic variables which is large enough and aligned + enough for storing socket address data structure of any family. For + example, code with a file descriptor and without the context of the + address family can pass a pointer to a variable of this type where a + pointer to a socket address structure is expected in calls such as + getpeername() and determine the address family by accessing the + received content after the call. + + The sockaddr_storage structure may also be useful and applied to + certain other interfaces where a generic socket address large enough + and aligned for use with multiple address families may be needed. A + discussion of those interfaces is outside the scope of this document. + + + + +Gilligan, et. al. Informational [Page 15] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + Also, much existing code assumes that any socket address structure + can fit in a generic sockaddr structure. While this has been true + for IPv4 socket address structures, it has always been false for Unix + domain socket address structures (but in practice this has not been a + problem) and it is also false for IPv6 socket address structures + (which can be a problem). + + So now an application can do the following: + + struct sockaddr_storage __ss; + struct sockaddr_in6 *sin6; + sin6 = (struct sockaddr_in6 *) &__ss; + +4. Interface Identification + + This API uses an interface index (a small positive integer) to + identify the local interface on which a multicast group is joined + (Section 5.3). Additionally, the advanced API [4] uses these same + interface indexes to identify the interface on which a datagram is + received, or to specify the interface on which a datagram is to be + sent. + + Interfaces are normally known by names such as "le0", "sl1", "ppp2", + and the like. On Berkeley-derived implementations, when an interface + is made known to the system, the kernel assigns a unique positive + integer value (called the interface index) to that interface. These + are small positive integers that start at 1. (Note that 0 is never + used for an interface index.) There may be gaps so that there is no + current interface for a particular positive interface index. + + This API defines two functions that map between an interface name and + index, a third function that returns all the interface names and + indexes, and a fourth function to return the dynamic memory allocated + by the previous function. How these functions are implemented is + left up to the implementation. 4.4BSD implementations can implement + these functions using the existing sysctl() function with the + NET_RT_IFLIST command. Other implementations may wish to use ioctl() + for this purpose. + +4.1 Name-to-Index + + The first function maps an interface name into its corresponding + index. + + #include + + unsigned int if_nametoindex(const char *ifname); + + + + +Gilligan, et. al. Informational [Page 16] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + If the specified interface name does not exist, the return value is + 0, and errno is set to ENXIO. If there was a system error (such as + running out of memory), the return value is 0 and errno is set to the + proper value (e.g., ENOMEM). + +4.2 Index-to-Name + + The second function maps an interface index into its corresponding + name. + + #include + + char *if_indextoname(unsigned int ifindex, char *ifname); + + The ifname argument must point to a buffer of at least IF_NAMESIZE + bytes into which the interface name corresponding to the specified + index is returned. (IF_NAMESIZE is also defined in and + its value includes a terminating null byte at the end of the + interface name.) This pointer is also the return value of the + function. If there is no interface corresponding to the specified + index, NULL is returned, and errno is set to ENXIO, if there was a + system error (such as running out of memory), if_indextoname returns + NULL and errno would be set to the proper value (e.g., ENOMEM). + +4.3 Return All Interface Names and Indexes + + The if_nameindex structure holds the information about a single + interface and is defined as a result of including the + header. + + struct if_nameindex { + unsigned int if_index; /* 1, 2, ... */ + char *if_name; /* null terminated name: "le0", ... */ + }; + + The final function returns an array of if_nameindex structures, one + structure per interface. + + struct if_nameindex *if_nameindex(void); + + The end of the array of structures is indicated by a structure with + an if_index of 0 and an if_name of NULL. The function returns a NULL + pointer upon an error, and would set errno to the appropriate value. + + The memory used for this array of structures along with the interface + names pointed to by the if_name members is obtained dynamically. + This memory is freed by the next function. + + + + +Gilligan, et. al. Informational [Page 17] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + +4.4 Free Memory + + The following function frees the dynamic memory that was allocated by + if_nameindex(). + + #include + + void if_freenameindex(struct if_nameindex *ptr); + + The argument to this function must be a pointer that was returned by + if_nameindex(). + + Currently net/if.h doesn't have prototype definitions for functions + and it is recommended that these definitions be defined in net/if.h + as well and the struct if_nameindex{}. + +5. Socket Options + + A number of new socket options are defined for IPv6. All of these + new options are at the IPPROTO_IPV6 level. That is, the "level" + parameter in the getsockopt() and setsockopt() calls is IPPROTO_IPV6 + when using these options. The constant name prefix IPV6_ is used in + all of the new socket options. This serves to clearly identify these + options as applying to IPv6. + + The declaration for IPPROTO_IPV6, the new IPv6 socket options, and + related constants defined in this section are obtained by including + the header . + +5.1 Unicast Hop Limit + + A new setsockopt() option controls the hop limit used in outgoing + unicast IPv6 packets. The name of this option is IPV6_UNICAST_HOPS, + and it is used at the IPPROTO_IPV6 layer. The following example + illustrates how it is used: + + int hoplimit = 10; + + if (setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, + (char *) &hoplimit, sizeof(hoplimit)) == -1) + perror("setsockopt IPV6_UNICAST_HOPS"); + + When the IPV6_UNICAST_HOPS option is set with setsockopt(), the + option value given is used as the hop limit for all subsequent + unicast packets sent via that socket. If the option is not set, the + system selects a default value. The integer hop limit value (called + x) is interpreted as follows: + + + + +Gilligan, et. al. Informational [Page 18] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 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 + + The IPV6_UNICAST_HOPS option may be used with getsockopt() to + determine the hop limit value that the system will use for subsequent + unicast packets sent via that socket. For example: + + int hoplimit; + size_t len = sizeof(hoplimit); + + if (getsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, + (char *) &hoplimit, &len) == -1) + perror("getsockopt IPV6_UNICAST_HOPS"); + else + printf("Using %d for hop limit.\n", hoplimit); + +5.2 Sending and Receiving Multicast Packets + + IPv6 applications may send UDP multicast packets by simply specifying + an IPv6 multicast address in the address argument of the sendto() + function. + + Three socket options at the IPPROTO_IPV6 layer control some of the + parameters for sending multicast packets. Setting these options is + not required: applications may send multicast packets without using + these options. The setsockopt() options for controlling the sending + of multicast packets are summarized below. These three options can + also be used with getsockopt(). + + IPV6_MULTICAST_IF + + Set the interface to use for outgoing multicast packets. The + argument is the index of the interface to use. + + Argument type: unsigned int + + IPV6_MULTICAST_HOPS + + Set the hop limit to use for outgoing multicast packets. (Note + a separate option - IPV6_UNICAST_HOPS - is provided to set the + hop limit to use for outgoing unicast packets.) + + The interpretation of the argument is the same as for the + IPV6_UNICAST_HOPS option: + + + + + +Gilligan, et. al. Informational [Page 19] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 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 + + If IPV6_MULTICAST_HOPS is not set, the default is 1 + (same as IPv4 today) + + Argument type: int + + IPV6_MULTICAST_LOOP + + If a multicast datagram is sent to a group to which the sending + host itself belongs (on the outgoing interface), a copy of the + datagram is looped back by the IP layer for local delivery if + this option is set to 1. If this option is set to 0 a copy + is not looped back. Other option values return an error of + EINVAL. + + If IPV6_MULTICAST_LOOP is not set, the default is 1 (loopback; + same as IPv4 today). + + Argument type: unsigned int + + The reception of multicast packets is controlled by the two + setsockopt() options summarized below. An error of EOPNOTSUPP is + returned if these two options are used with getsockopt(). + + IPV6_JOIN_GROUP + + Join a multicast group on a specified local interface. If the + interface index is specified as 0, the kernel chooses the local + interface. For example, some kernels look up the multicast + group in the normal IPv6 routing table and using the resulting + interface. + + Argument type: struct ipv6_mreq + + IPV6_LEAVE_GROUP + + Leave a multicast group on a specified interface. + + Argument type: struct ipv6_mreq + + The argument type of both of these options is the ipv6_mreq structure, + defined as a result of including the header; + + + + + +Gilligan, et. al. Informational [Page 20] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + struct ipv6_mreq { + struct in6_addr ipv6mr_multiaddr; /* IPv6 multicast addr */ + unsigned int ipv6mr_interface; /* interface index */ + }; + + Note that to receive multicast datagrams a process must join the + multicast group and bind the UDP port to which datagrams will be + sent. Some processes also bind the multicast group address to the + socket, in addition to the port, to prevent other datagrams destined + to that same port from being delivered to the socket. + +6. Library Functions + + New library functions are needed to perform a variety of operations + with IPv6 addresses. Functions are needed to lookup IPv6 addresses + in the Domain Name System (DNS). Both forward lookup (nodename-to- + address translation) and reverse lookup (address-to-nodename + translation) need to be supported. Functions are also needed to + convert IPv6 addresses between their binary and textual form. + + We note that the two existing functions, gethostbyname() and + gethostbyaddr(), are left as-is. New functions are defined to handle + both IPv4 and IPv6 addresses. + +6.1 Nodename-to-Address Translation + + The commonly used function gethostbyname() is inadequate for many + applications, first because it provides no way for the caller to + specify anything about the types of addresses desired (IPv4 only, + IPv6 only, IPv4-mapped IPv6 are OK, etc.), and second because many + implementations of this function are not thread safe. RFC 2133 + defined a function named gethostbyname2() but this function was also + inadequate, first because its use required setting a global option + (RES_USE_INET6) when IPv6 addresses were required, and second because + a flag argument is needed to provide the caller with additional + control over the types of addresses required. + + The following function is new and must be thread safe: + + #include + #include + + struct hostent *getipnodebyname(const char *name, int af, int flags + int *error_num); + + The name argument can be either a node name or a numeric address + string (i.e., a dotted-decimal IPv4 address or an IPv6 hex address). + The af argument specifies the address family, either AF_INET or + + + +Gilligan, et. al. Informational [Page 21] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + AF_INET6. The error_num value is returned to the caller, via a + pointer, with the appropriate error code in error_num, to support + thread safe error code returns. error_num will be set to one of the + following values: + + HOST_NOT_FOUND + + No such host is known. + + NO_ADDRESS + + The server recognised the request and the name but no address is + available. Another type of request to the name server for the + domain might return an answer. + + NO_RECOVERY + + An unexpected server failure occurred which cannot be recovered. + + TRY_AGAIN + + A temporary and possibly transient error occurred, such as a + failure of a server to respond. + + The flags argument specifies the types of addresses that are searched + for, and the types of addresses that are returned. We note that a + special flags value of AI_DEFAULT (defined below) should handle most + applications. + + That is, porting simple applications to use IPv6 replaces the call + + hptr = gethostbyname(name); + + with + + hptr = getipnodebyname(name, AF_INET6, AI_DEFAULT, &error_num); + + and changes any subsequent error diagnosis code to use error_num + instead of externally declared variables, such as h_errno. + + Applications desiring finer control over the types of addresses + searched for and returned, can specify other combinations of the + flags argument. + + + + + + + + +Gilligan, et. al. Informational [Page 22] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + A flags of 0 implies a strict interpretation of the af argument: + + - If flags is 0 and af is AF_INET, then the caller wants only + IPv4 addresses. A query is made for A records. If successful, + the IPv4 addresses are returned and the h_length member of the + hostent structure will be 4, else the function returns a NULL + pointer. + + - If flags is 0 and if af is AF_INET6, then the caller wants only + IPv6 addresses. A query is made for AAAA records. If + successful, the IPv6 addresses are returned and the h_length + member of the hostent structure will be 16, else the function + returns a NULL pointer. + + Other constants can be logically-ORed into the flags argument, to + modify the behavior of the function. + + - If the AI_V4MAPPED flag is specified along with an af of + AF_INET6, then the caller will accept IPv4-mapped IPv6 + addresses. That is, if no AAAA records are found then a query + is made for A records and any found are returned as IPv4-mapped + IPv6 addresses (h_length will be 16). The AI_V4MAPPED flag is + ignored unless af equals AF_INET6. + + - The AI_ALL flag is used in conjunction with the AI_V4MAPPED + flag, and is only used with the IPv6 address family. When AI_ALL + is logically or'd with AI_V4MAPPED flag then the caller wants + all addresses: IPv6 and IPv4-mapped IPv6. A query is first made + for AAAA records and if successful, the IPv6 addresses are + returned. Another query is then made for A records and any found + are returned as IPv4-mapped IPv6 addresses. h_length will be 16. + Only if both queries fail does the function return a NULL pointer. + This flag is ignored unless af equals AF_INET6. + + - The AI_ADDRCONFIG flag specifies that a query for AAAA records + should occur only if the node has at least one IPv6 source + address configured and a query for A records should occur only + if the node has at least one IPv4 source address configured. + + For example, if the node has no IPv6 source addresses + configured, and af equals AF_INET6, and the node name being + looked up has both AAAA and A records, then: + + (a) if only AI_ADDRCONFIG is specified, the function + returns a NULL pointer; + (b) if AI_ADDRCONFIG | AI_V4MAPPED is specified, the A + records are returned as IPv4-mapped IPv6 addresses; + + + + +Gilligan, et. al. Informational [Page 23] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + The special flags value of AI_DEFAULT is defined as + + #define AI_DEFAULT (AI_V4MAPPED | AI_ADDRCONFIG) + + We noted that the getipnodebyname() function must allow the name + argument to be either a node name or a literal address string (i.e., + a dotted-decimal IPv4 address or an IPv6 hex address). This saves + applications from having to call inet_pton() to handle literal + address strings. + + There are four scenarios based on the type of literal address string + and the value of the af argument. + + The two simple cases are: + + When name is a dotted-decimal IPv4 address and af equals AF_INET, or + when name is an IPv6 hex address and af equals AF_INET6. The members + of the returned hostent structure are: h_name points to a copy of the + name argument, h_aliases is a NULL pointer, h_addrtype is a copy of + the af argument, h_length is either 4 (for AF_INET) or 16 (for + AF_INET6), h_addr_list[0] is a pointer to the 4-byte or 16-byte + binary address, and h_addr_list[1] is a NULL pointer. + + When name is a dotted-decimal IPv4 address and af equals AF_INET6, + and flags equals AI_V4MAPPED, an IPv4-mapped IPv6 address is + returned: h_name points to an IPv6 hex address containing the IPv4- + mapped IPv6 address, h_aliases is a NULL pointer, h_addrtype is + AF_INET6, h_length is 16, h_addr_list[0] is a pointer to the 16-byte + binary address, and h_addr_list[1] is a NULL pointer. If AI_V4MAPPED + is set (with or without AI_ALL) return IPv4-mapped otherwise return + NULL. + + It is an error when name is an IPv6 hex address and af equals + AF_INET. The function's return value is a NULL pointer and error_num + equals HOST_NOT_FOUND. + +6.2 Address-To-Nodename Translation + + The following function has the same arguments as the existing + gethostbyaddr() function, but adds an error number. + + #include #include + + struct hostent *getipnodebyaddr(const void *src, size_t len, + int af, int *error_num); + + + + + + +Gilligan, et. al. Informational [Page 24] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + As with getipnodebyname(), getipnodebyaddr() must be thread safe. + The error_num value is returned to the caller with the appropriate + error code, to support thread safe error code returns. The following + error conditions may be returned for error_num: + + HOST_NOT_FOUND + + No such host is known. + + NO_ADDRESS + + The server recognized the request and the name but no address + is available. Another type of request to the name server for + the domain might return an answer. + + NO_RECOVERY + + An unexpected server failure occurred which cannot be + recovered. + + TRY_AGAIN + + A temporary and possibly transient error occurred, such as a + failure of a server to respond. + + One possible source of confusion is the handling of IPv4-mapped IPv6 + addresses and IPv4-compatible IPv6 addresses, but the following logic + should apply. + + 1. If af is AF_INET6, and if len equals 16, and if the IPv6 + address is an IPv4-mapped IPv6 address or an IPv4-compatible + IPv6 address, then skip over the first 12 bytes of the IPv6 + address, set af to AF_INET, and set len to 4. + + 2. If af is AF_INET, lookup the name for the given IPv4 address + (e.g., query for a PTR record in the in-addr.arpa domain). + + 3. If af is AF_INET6, lookup the name for the given IPv6 address + (e.g., query for a PTR record in the ip6.int domain). + + 4. If the function is returning success, then the single address + that is returned in the hostent structure is a copy of the + first argument to the function with the same address family + that was passed as an argument to this function. + + + + + + + +Gilligan, et. al. Informational [Page 25] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + All four steps listed are performed, in order. Also note that the + IPv6 hex addresses "::" and "::1" MUST NOT be treated as IPv4- + compatible addresses, and if the address is "::", HOST_NOT_FOUND MUST + be returned and a query of the address not performed. + + Also for the macro in section 6.7 IN6_IS_ADDR_V4COMPAT MUST return + false for "::" and "::1". + +6.3 Freeing memory for getipnodebyname and getipnodebyaddr + + The hostent structure does not change from its existing definition. + This structure, and the information pointed to by this structure, are + dynamically allocated by getipnodebyname and getipnodebyaddr. The + following function frees this memory: + + #include + + void freehostent(struct hostent *ptr); + +6.4 Protocol-Independent Nodename and Service Name Translation + + Nodename-to-address translation is done in a protocol-independent + fashion using the getaddrinfo() function that is taken from the + Institute of Electrical and Electronic Engineers (IEEE) POSIX 1003.1g + (Protocol Independent Interfaces) draft specification [3]. + + The official specification for this function will be the final POSIX + standard, with the following additional requirements: + + - getaddrinfo() (along with the getnameinfo() function described + in the next section) must be thread safe. + + - The AI_NUMERICHOST is new with this document. + + - All fields in socket address structures returned by + getaddrinfo() that are not filled in through an explicit + argument (e.g., sin6_flowinfo and sin_zero) must be set to 0. + (This makes it easier to compare socket address structures.) + + - getaddrinfo() must fill in the length field of a socket address + structure (e.g., sin6_len) on systems that support this field. + + We are providing this independent description of the function because + POSIX standards are not freely available (as are IETF documents). + + #include + #include + + + + +Gilligan, et. al. Informational [Page 26] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + int getaddrinfo(const char *nodename, const char *servname, + const struct addrinfo *hints, + struct addrinfo **res); + + The addrinfo structure is defined as a result of including the + header. + + struct addrinfo { + int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* length of ai_addr */ + char *ai_canonname; /* canonical name for nodename */ + struct sockaddr *ai_addr; /* binary address */ + struct addrinfo *ai_next; /* next structure in linked list */ + }; + + The return value from the function is 0 upon success or a nonzero + error code. The following names are the nonzero error codes from + getaddrinfo(), and are defined in : + + EAI_ADDRFAMILY address family for nodename not supported + EAI_AGAIN temporary failure in name resolution + EAI_BADFLAGS invalid value for ai_flags + EAI_FAIL non-recoverable failure in name resolution + EAI_FAMILY ai_family not supported + EAI_MEMORY memory allocation failure + EAI_NODATA no address associated with nodename + EAI_NONAME nodename nor servname provided, or not known + EAI_SERVICE servname not supported for ai_socktype + EAI_SOCKTYPE ai_socktype not supported + EAI_SYSTEM system error returned in errno + + The nodename and servname arguments are pointers to null-terminated + strings or NULL. One or both of these two arguments must be a non- + NULL pointer. In the normal client scenario, both the nodename and + servname are specified. In the normal server scenario, only the + servname is specified. A non-NULL nodename string can be either a + node name or a numeric host address string (i.e., a dotted-decimal + IPv4 address or an IPv6 hex address). A non-NULL servname string can + be either a service name or a decimal port number. + + The caller can optionally pass an addrinfo structure, pointed to by + the third argument, to provide hints concerning the type of socket + that the caller supports. In this hints structure all members other + than ai_flags, ai_family, ai_socktype, and ai_protocol must be zero + or a NULL pointer. A value of PF_UNSPEC for ai_family means the + + + +Gilligan, et. al. Informational [Page 27] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + caller will accept any protocol family. A value of 0 for ai_socktype + means the caller will accept any socket type. A value of 0 for + ai_protocol means the caller will accept any protocol. For example, + if the caller handles only TCP and not UDP, then the ai_socktype + member of the hints structure should be set to SOCK_STREAM when + getaddrinfo() is called. If the caller handles only IPv4 and not + IPv6, then the ai_family member of the hints structure should be set + to PF_INET when getaddrinfo() is called. If the third argument to + getaddrinfo() is a NULL pointer, this is the same as if the caller + had filled in an addrinfo structure initialized to zero with + ai_family set to PF_UNSPEC. + + Upon successful return a pointer to a linked list of one or more + addrinfo structures is returned through the final argument. The + caller can process each addrinfo structure in this list by following + the ai_next pointer, until a NULL pointer is encountered. In each + returned addrinfo structure the three members ai_family, ai_socktype, + and ai_protocol are the corresponding arguments for a call to the + socket() function. In each addrinfo structure the ai_addr member + points to a filled-in socket address structure whose length is + specified by the ai_addrlen member. + + If the AI_PASSIVE bit is set in the ai_flags member of the hints + structure, then the caller plans to use the returned socket address + structure in a call to bind(). In this case, if the nodename + argument is a NULL pointer, then the IP address portion of the socket + address structure will be set to INADDR_ANY for an IPv4 address or + IN6ADDR_ANY_INIT for an IPv6 address. + + If the AI_PASSIVE bit is not set in the ai_flags member of the hints + structure, then the returned socket address structure will be ready + for a call to connect() (for a connection-oriented protocol) or + either connect(), sendto(), or sendmsg() (for a connectionless + protocol). In this case, if the nodename argument is a NULL pointer, + then the IP address portion of the socket address structure will be + set to the loopback address. + + If the AI_CANONNAME bit is set in the ai_flags member of the hints + structure, then upon successful return the ai_canonname member of the + first addrinfo structure in the linked list will point to a null- + terminated string containing the canonical name of the specified + nodename. + + If the AI_NUMERICHOST bit is set in the ai_flags member of the hints + structure, then a non-NULL nodename string must be a numeric host + address string. Otherwise an error of EAI_NONAME is returned. This + flag prevents any type of name resolution service (e.g., the DNS) + from being called. + + + +Gilligan, et. al. Informational [Page 28] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + All of the information returned by getaddrinfo() is dynamically + allocated: the addrinfo structures, and the socket address structures + and canonical node name strings pointed to by the addrinfo + structures. To return this information to the system the function + freeaddrinfo() is called: + + #include #include + + void freeaddrinfo(struct addrinfo *ai); + + The addrinfo structure pointed to by the ai argument is freed, along + with any dynamic storage pointed to by the structure. This operation + is repeated until a NULL ai_next pointer is encountered. + + To aid applications in printing error messages based on the EAI_xxx + codes returned by getaddrinfo(), the following function is defined. + + #include #include + + char *gai_strerror(int ecode); + + The argument is one of the EAI_xxx values defined earlier and the + return value points to a string describing the error. If the + argument is not one of the EAI_xxx values, the function still returns + a pointer to a string whose contents indicate an unknown error. + +6.5 Socket Address Structure to Nodename and Service Name + + The POSIX 1003.1g specification includes no function to perform the + reverse conversion from getaddrinfo(): to look up a nodename and + service name, given the binary address and port. Therefore, we + define the following function: + + #include + #include + + int getnameinfo(const struct sockaddr *sa, socklen_t salen, + char *host, size_t hostlen, + char *serv, size_t servlen, + int flags); + + This function looks up an IP address and port number provided by the + caller in the DNS and system-specific database, and returns text + strings for both in buffers provided by the caller. The function + indicates successful completion by a zero return value; a non-zero + return value indicates failure. + + + + + +Gilligan, et. al. Informational [Page 29] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + The first argument, sa, points to either a sockaddr_in structure (for + IPv4) or a sockaddr_in6 structure (for IPv6) that holds the IP + address and port number. The salen argument gives the length of the + sockaddr_in or sockaddr_in6 structure. + + The function returns the nodename associated with the IP address in + the buffer pointed to by the host argument. The caller provides the + size of this buffer via the hostlen argument. The service name + associated with the port number is returned in the buffer pointed to + by serv, and the servlen argument gives the length of this buffer. + The caller specifies not to return either string by providing a zero + value for the hostlen or servlen arguments. Otherwise, the caller + must provide buffers large enough to hold the nodename and the + service name, including the terminating null characters. + + Unfortunately most systems do not provide constants that specify the + maximum size of either a fully-qualified domain name or a service + name. Therefore to aid the application in allocating buffers for + these two returned strings the following constants are defined in + : + + #define NI_MAXHOST 1025 + #define NI_MAXSERV 32 + + The first value is actually defined as the constant MAXDNAME in recent + versions of BIND's header (older versions of BIND + define this constant to be 256) and the second is a guess based on the + services listed in the current Assigned Numbers RFC. + + The final argument is a flag that changes the default actions of this + function. By default the fully-qualified domain name (FQDN) for the + host is looked up in the DNS and returned. If the flag bit NI_NOFQDN + is set, only the nodename portion of the FQDN is returned for local + hosts. + + If the flag bit NI_NUMERICHOST is set, or if the host's name cannot be + located in the DNS, the numeric form of the host's address is returned + instead of its name (e.g., by calling inet_ntop() instead of + getipnodebyaddr()). If the flag bit NI_NAMEREQD is set, an error is + returned if the host's name cannot be located in the DNS. + + If the flag bit NI_NUMERICSERV is set, the numeric form of the service + address is returned (e.g., its port number) instead of its name. The + two NI_NUMERICxxx flags are required to support the "-n" flag that + many commands provide. + + + + + + +Gilligan, et. al. Informational [Page 30] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + A fifth flag bit, NI_DGRAM, specifies that the service is a datagram + service, and causes getservbyport() to be called with a second + argument of "udp" instead of its default of "tcp". This is required + for the few ports (e.g. 512-514) that have different services for UDP + and TCP. + + These NI_xxx flags are defined in along with the AI_xxx + flags already defined for getaddrinfo(). + +6.6 Address Conversion Functions + + The two functions inet_addr() and inet_ntoa() convert an IPv4 address + between binary and text form. IPv6 applications need similar + functions. The following two functions convert both IPv6 and IPv4 + addresses: + + #include + #include + + int inet_pton(int af, const char *src, void *dst); + + const char *inet_ntop(int af, const void *src, + char *dst, size_t size); + + The inet_pton() function converts an address in its standard text + presentation form into its numeric binary form. The af argument + specifies the family of the address. Currently the AF_INET and + AF_INET6 address families are supported. The src argument points to + the string being passed in. The dst argument points to a buffer into + which the function stores the numeric address. The address is + returned in network byte order. Inet_pton() returns 1 if the + conversion succeeds, 0 if the input is not a valid IPv4 dotted- + decimal string or a valid IPv6 address string, or -1 with errno set + to EAFNOSUPPORT if the af argument is unknown. The calling + application must ensure that the buffer referred to by dst is large + enough to hold the numeric address (e.g., 4 bytes for AF_INET or 16 + bytes for AF_INET6). + + If the af argument is AF_INET, the function accepts a string in the + standard IPv4 dotted-decimal form: + + ddd.ddd.ddd.ddd + + where ddd is a one to three digit decimal number between 0 and 255. + Note that many implementations of the existing inet_addr() and + inet_aton() functions accept nonstandard input: octal numbers, + hexadecimal numbers, and fewer than four numbers. inet_pton() does + not accept these formats. + + + +Gilligan, et. al. Informational [Page 31] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + If the af argument is AF_INET6, then the function accepts a string in + one of the standard IPv6 text forms defined in Section 2.2 of the + addressing architecture specification [2]. + + The inet_ntop() function converts a numeric address into a text + string suitable for presentation. The af argument specifies the + family of the address. This can be AF_INET or AF_INET6. The src + argument points to a buffer holding an IPv4 address if the af + argument is AF_INET, or an IPv6 address if the af argument is + AF_INET6, the address must be in network byte order. The dst + argument points to a buffer where the function will store the + resulting text string. The size argument specifies the size of this + buffer. The application must specify a non-NULL dst argument. For + IPv6 addresses, the buffer must be at least 46-octets. For IPv4 + addresses, the buffer must be at least 16-octets. In order to allow + applications to easily declare buffers of the proper size to store + IPv4 and IPv6 addresses in string form, the following two constants + are defined in : + + #define INET_ADDRSTRLEN 16 + #define INET6_ADDRSTRLEN 46 + + The inet_ntop() function returns a pointer to the buffer containing + the text string if the conversion succeeds, and NULL otherwise. Upon + failure, errno is set to EAFNOSUPPORT if the af argument is invalid or + ENOSPC if the size of the result buffer is inadequate. + +6.7 Address Testing Macros + + The following macros can be used to test for special IPv6 addresses. + + #include + + int IN6_IS_ADDR_UNSPECIFIED (const struct in6_addr *); + int IN6_IS_ADDR_LOOPBACK (const struct in6_addr *); + int IN6_IS_ADDR_MULTICAST (const struct in6_addr *); + int IN6_IS_ADDR_LINKLOCAL (const struct in6_addr *); + int IN6_IS_ADDR_SITELOCAL (const struct in6_addr *); + int IN6_IS_ADDR_V4MAPPED (const struct in6_addr *); + int IN6_IS_ADDR_V4COMPAT (const struct in6_addr *); + + int IN6_IS_ADDR_MC_NODELOCAL(const struct in6_addr *); + int IN6_IS_ADDR_MC_LINKLOCAL(const struct in6_addr *); + int IN6_IS_ADDR_MC_SITELOCAL(const struct in6_addr *); + int IN6_IS_ADDR_MC_ORGLOCAL (const struct in6_addr *); + int IN6_IS_ADDR_MC_GLOBAL (const struct in6_addr *); + + + + + +Gilligan, et. al. Informational [Page 32] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + The first seven macros return true if the address is of the specified + type, or false otherwise. The last five test the scope of a + multicast address and return true if the address is a multicast + address of the specified scope or false if the address is either not + a multicast address or not of the specified scope. Note that + IN6_IS_ADDR_LINKLOCAL and IN6_IS_ADDR_SITELOCAL return true only for + the two local-use IPv6 unicast addresses. These two macros do not + return true for IPv6 multicast addresses of either link-local scope + or site-local scope. + +7. Summary of New Definitions + + The following list summarizes the constants, structure, and extern + definitions discussed in this memo, sorted by header. + + IF_NAMESIZE + struct if_nameindex{}; + + AI_ADDRCONFIG + AI_DEFAULT + AI_ALL + AI_CANONNAME + AI_NUMERICHOST + AI_PASSIVE + AI_V4MAPPED + EAI_ADDRFAMILY + EAI_AGAIN + EAI_BADFLAGS + EAI_FAIL + EAI_FAMILY + EAI_MEMORY + EAI_NODATA + EAI_NONAME + EAI_SERVICE + EAI_SOCKTYPE + EAI_SYSTEM + NI_DGRAM + NI_MAXHOST + NI_MAXSERV + NI_NAMEREQD + NI_NOFQDN + NI_NUMERICHOST + NI_NUMERICSERV + struct addrinfo{}; + + IN6ADDR_ANY_INIT + IN6ADDR_LOOPBACK_INIT + INET6_ADDRSTRLEN + + + +Gilligan, et. al. Informational [Page 33] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + INET_ADDRSTRLEN + IPPROTO_IPV6 + IPV6_JOIN_GROUP + IPV6_LEAVE_GROUP + IPV6_MULTICAST_HOPS + IPV6_MULTICAST_IF + IPV6_MULTICAST_LOOP + IPV6_UNICAST_HOPS + SIN6_LEN + extern const struct in6_addr in6addr_any; + extern const struct in6_addr in6addr_loopback; + struct in6_addr{}; + struct ipv6_mreq{}; + struct sockaddr_in6{}; + + AF_INET6 + PF_INET6 + struct sockaddr_storage; + + The following list summarizes the function and macro prototypes + discussed in this memo, sorted by header. + + int inet_pton(int, const char *, void *); + const char *inet_ntop(int, const void *, + char *, size_t); + + char *if_indextoname(unsigned int, char *); + unsigned int if_nametoindex(const char *); + void if_freenameindex(struct if_nameindex *); + struct if_nameindex *if_nameindex(void); + + int getaddrinfo(const char *, const char *, + const struct addrinfo *, + struct addrinfo **); + int getnameinfo(const struct sockaddr *, socklen_t, + char *, size_t, char *, size_t, int); + void freeaddrinfo(struct addrinfo *); + char *gai_strerror(int); + struct hostent *getipnodebyname(const char *, int, int, + int *); + struct hostent *getipnodebyaddr(const void *, size_t, + int, int *); + void freehostent(struct hostent *); + + int IN6_IS_ADDR_LINKLOCAL(const struct in6_addr *); + int IN6_IS_ADDR_LOOPBACK(const struct in6_addr *); + int IN6_IS_ADDR_MC_GLOBAL(const struct in6_addr *); + int IN6_IS_ADDR_MC_LINKLOCAL(const struct in6_addr *); + + + +Gilligan, et. al. Informational [Page 34] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + int IN6_IS_ADDR_MC_NODELOCAL(const struct in6_addr *); + int IN6_IS_ADDR_MC_ORGLOCAL(const struct in6_addr *); + int IN6_IS_ADDR_MC_SITELOCAL(const struct in6_addr *); + int IN6_IS_ADDR_MULTICAST(const struct in6_addr *); + int IN6_IS_ADDR_SITELOCAL(const struct in6_addr *); + int IN6_IS_ADDR_UNSPECIFIED(const struct in6_addr *); + int IN6_IS_ADDR_V4COMPAT(const struct in6_addr *); + int IN6_IS_ADDR_V4MAPPED(const struct in6_addr *); + +8. Security Considerations + + IPv6 provides a number of new security mechanisms, many of which need + to be accessible to applications. Companion memos detailing the + extensions to the socket interfaces to support IPv6 security are + being written. + +9. Year 2000 Considerations + + There are no issues for this memo concerning the Year 2000 issue + regarding the use of dates. + +Changes From RFC 2133 + + Changes made in the March 1998 Edition (-01 draft): + + Changed all "hostname" to "nodename" for consistency with other + IPv6 documents. + + Section 3.3: changed comment for sin6_flowinfo to be "traffic + class & flow info" and updated corresponding text description to + current definition of these two fields. + + Section 3.10 ("Portability Additions") is new. + + Section 6: a new paragraph was added reiterating that the existing + gethostbyname() and gethostbyaddr() are not changed. + + Section 6.1: change gethostbyname3() to getnodebyname(). Add + AI_DEFAULT to handle majority of applications. Renamed + AI_V6ADDRCONFIG to AI_ADDRCONFIG and define it for A records and + IPv4 addresses too. Defined exactly what getnodebyname() must + return if the name argument is a numeric address string. + + Section 6.2: change gethostbyaddr() to getnodebyaddr(). Reword + items 2 and 3 in the description of how to handle IPv4-mapped and + IPv4- compatible addresses to "lookup a name" for a given address, + instead of specifying what type of DNS query to issue. + + + + +Gilligan, et. al. Informational [Page 35] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + Section 6.3: added two more requirements to getaddrinfo(). + + Section 7: added the following constants to the list for + : AI_ADDRCONFIG, AI_ALL, and AI_V4MAPPED. Add union + sockaddr_union and SA_LEN to the lists for . + + Updated references. + + Changes made in the November 1997 Edition (-00 draft): + + The data types have been changed to conform with Draft 6.6 of the + Posix 1003.1g standard. + + Section 3.2: data type of s6_addr changed to "uint8_t". + + Section 3.3: data type of sin6_family changed to "sa_family_t". + data type of sin6_port changed to "in_port_t", data type of + sin6_flowinfo changed to "uint32_t". + + Section 3.4: same as Section 3.3, plus data type of sin6_len + changed to "uint8_t". + + Section 6.2: first argument of gethostbyaddr() changed from "const + char *" to "const void *" and second argument changed from "int" + to "size_t". + + Section 6.4: second argument of getnameinfo() changed from + "size_t" to "socklen_t". + + The wording was changed when new structures were defined, to be + more explicit as to which header must be included to define the + structure: + + Section 3.2 (in6_addr{}), Section 3.3 (sockaddr_in6{}), Section + 3.4 (sockaddr_in6{}), Section 4.3 (if_nameindex{}), Section 5.3 + (ipv6_mreq{}), and Section 6.3 (addrinfo{}). + + Section 4: NET_RT_LIST changed to NET_RT_IFLIST. + + Section 5.1: The IPV6_ADDRFORM socket option was removed. + + Section 5.3: Added a note that an option value other than 0 or 1 + for IPV6_MULTICAST_LOOP returns an error. Added a note that + IPV6_MULTICAST_IF, IPV6_MULTICAST_HOPS, and IPV6_MULTICAST_LOOP + can also be used with getsockopt(), but IPV6_ADD_MEMBERSHIP and + IPV6_DROP_MEMBERSHIP cannot be used with getsockopt(). + + + + + +Gilligan, et. al. Informational [Page 36] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + Section 6.1: Removed the description of gethostbyname2() and its + associated RES_USE_INET6 option, replacing it with + gethostbyname3(). + + Section 6.2: Added requirement that gethostbyaddr() be thread + safe. Reworded step 4 to avoid using the RES_USE_INET6 option. + + Section 6.3: Added the requirement that getaddrinfo() and + getnameinfo() be thread safe. Added the AI_NUMERICHOST flag. + + Section 6.6: Added clarification about IN6_IS_ADDR_LINKLOCAL and + IN6_IS_ADDR_SITELOCAL macros. + + Changes made to the draft -01 specification Sept 98 + + Changed priority to traffic class in the spec. + + Added the need for scope identification in section 2.1. + + Added sin6_scope_id to struct sockaddr_in6 in sections 3.3 and + 3.4. + + Changed 3.10 to use generic storage structure to support holding + IPv6 addresses and removed the SA_LEN macro. + + Distinguished between invalid input parameters and system failures + for Interface Identification in Section 4.1 and 4.2. + + Added defaults for multicast operations in section 5.2 and changed + the names from ADD to JOIN and DROP to LEAVE to be consistent with + IPv6 multicast terminology. + + Changed getnodebyname to getipnodebyname, getnodebyaddr to + getipnodebyaddr, and added MT safe error code to function + parameters in section 6. + + Moved freehostent to its own sub-section after getipnodebyaddr now + 6.3 (so this bumps all remaining sections in section 6. + + Clarified the use of AI_ALL and AI_V4MAPPED that these are + dependent on the AF parameter and must be used as a conjunction in + section 6.1. + + Removed the restriction that literal addresses cannot be used with + a flags argument in section 6.1. + + Added Year 2000 Section to the draft + + + + +Gilligan, et. al. Informational [Page 37] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + Deleted Reference to the following because the attached is deleted + from the ID directory and has expired. But the logic from the + aforementioned draft still applies, so that was kept in Section + 6.2 bullets after 3rd paragraph. + + [7] P. Vixie, "Reverse Name Lookups of Encapsulated IPv4 + Addresses in IPv6", Internet-Draft, , May 1996. + + Deleted the following reference as it is no longer referenced. + And the draft has expired. + + [3] D. McDonald, "A Simple IP Security API Extension to BSD + Sockets", Internet-Draft, , March 1997. + + Deleted the following reference as it is no longer referenced. + + [4] C. Metz, "Network Security API for Sockets", + Internet-Draft, , January + 1998. + + Update current references to current status. + + Added alignment notes for in6_addr and sin6_addr. + + Clarified further that AI_V4MAPPED must be used with a dotted IPv4 + literal address for getipnodebyname(), when address family is + AF_INET6. + + Added text to clarify "::" and "::1" when used by + getipnodebyaddr(). + +Acknowledgments + + Thanks to the many people who made suggestions and provided feedback + to this document, including: Werner Almesberger, Ran Atkinson, Fred + Baker, Dave Borman, Andrew Cherenson, Alex Conta, Alan Cox, Steve + Deering, Richard Draves, Francis Dupont, Robert Elz, Marc Hasson, Tom + Herbert, Bob Hinden, Wan-Yen Hsu, Christian Huitema, Koji Imada, + Markus Jork, Ron Lee, Alan Lloyd, Charles Lynn, Dan McDonald, Dave + Mitton, Thomas Narten, Josh Osborne, Craig Partridge, Jean-Luc + Richier, Erik Scoredos, Keith Sklower, Matt Thomas, Harvey Thompson, + Dean D. Throop, Karen Tracey, Glenn Trewitt, Paul Vixie, David + Waitzman, Carl Williams, and Kazu Yamamoto, + + + + + + +Gilligan, et. al. Informational [Page 38] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + + The getaddrinfo() and getnameinfo() functions are taken from an + earlier Internet Draft by Keith Sklower. As noted in that draft, + William Durst, Steven Wise, Michael Karels, and Eric Allman provided + many useful discussions on the subject of protocol-independent name- + to-address translation, and reviewed early versions of Keith + Sklower's original proposal. Eric Allman implemented the first + prototype of getaddrinfo(). The observation that specifying the pair + of name and service would suffice for connecting to a service + independent of protocol details was made by Marshall Rose in a + proposal to X/Open for a "Uniform Network Interface". + + Craig Metz, Jack McCann, Erik Nordmark, Tim Hartrick, and Mukesh + Kacker made many contributions to this document. Ramesh Govindan + made a number of contributions and co-authored an earlier version of + this memo. + +References + + [1] Deering, S. and R. Hinden, "Internet Protocol, Version 6 (IPv6) + Specification", RFC 2460, December 1998. + + [2] Hinden, R. and S. Deering, "IP Version 6 Addressing + Architecture", RFC 2373, July 1998. + + [3] IEEE, "Protocol Independent Interfaces", IEEE Std 1003.1g, DRAFT + 6.6, March 1997. + + [4] Stevens, W. and M. Thomas, "Advanced Sockets API for IPv6", RFC + 2292, February 1998. + + + + + + + + + + + + + + + + + + + + + + +Gilligan, et. al. Informational [Page 39] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + +Authors' Addresses + + Robert E. Gilligan + FreeGate Corporation + 1208 E. Arques Ave. + Sunnyvale, CA 94086 + + Phone: +1 408 617 1004 + EMail: gilligan@freegate.com + + + Susan Thomson + Bell Communications Research + MRE 2P-343, 445 South Street + Morristown, NJ 07960 + + Phone: +1 201 829 4514 + EMail: set@thumper.bellcore.com + + + Jim Bound + Compaq Computer Corporation + 110 Spitbrook Road ZK3-3/U14 + Nashua, NH 03062-2698 + + Phone: +1 603 884 0400 + EMail: bound@zk3.dec.com + + + W. Richard Stevens + 1202 E. Paseo del Zorro + Tucson, AZ 85718-2826 + + Phone: +1 520 297 9416 + EMail: rstevens@kohala.com + + + + + + + + + + + + + + + + +Gilligan, et. al. Informational [Page 40] + +RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999 + + +Full Copyright Statement + + Copyright (C) The Internet Society (1999). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + + + + + + + + + + + + + + + + + + + + + + + + +Gilligan, et. al. Informational [Page 41] +