RFC 4038 - Application Aspects of IPv6 Transition(3)

时间:2006-10-31 来源: 作者: 点击:
memset(hints,0,sizeof(hints)); hints.ai_family=AF_UNSPEC; hints.ai_socktype=SOCK_STREAM; error=getaddrinfo(SERVER_NODE,SERVICE,hints,res); if(error!=0){ /*handlegetaddrinfoerror*/ } sockfd=socket(res
  

      memset(&hints, 0, sizeof(hints));
      hints.ai_family = AF_UNSPEC;
      hints.ai_socktype = SOCK_STREAM;

      error = getaddrinfo(SERVER_NODE, SERVICE, &hints, &res);
      if (error != 0) {
           /* handle getaddrinfo error */
      }

      sockfd = socket(res->family, res->ai_socktype, res->ai_protocol);
      if (sockfd < 0) {
           /* handle socket error */
      }

      if (connect(sockfd, res->ai_addr, res->ai_addrlen) < 0 ) {
           /* handle connect error */
      }

      /* ... */

      freeaddrinfo(res);

6.2.3.  Binary/Presentation Format Conversion

   We should consider the binary and presentation address format
   conversion APIs.  The following functions convert network address
   structure in its presentation address format and vice versa:

      inet_ntop()
      inet_pton()

   Both are from the basic socket extensions for IPv6.  However, these
   conversion functions are protocol-dependent.  It is better to use
   getnameinfo()/getaddrinfo() (inet_pton and inet_ntop equivalents are
   described in Appendix A).

   Conversion from network address structure to presentation format can
   be written as follows:

      struct sockaddr_storage ss;
      char addrStr[INET6_ADDRSTRLEN];
      char servStr[NI_MAXSERV];
      int error;

      /* fill ss structure */

      error = getnameinfo((struct sockaddr *)&ss, sizeof(ss),
                          addrStr, sizeof(addrStr),
                          servStr, sizeof(servStr),
                          NI_NUMERICHOST);

   Conversions from presentation format to network address structure can
   be written as follows:

      struct addrinfo hints, *res;
      char addrStr[INET6_ADDRSTRLEN];
      int error;

      /* fill addrStr buffer */

      memset(&hints, 0, sizeof(hints));
      hints.ai_family = AF_UNSPEC;

      error = getaddrinfo(addrStr, NULL, &hints, &res);
      if (error != 0) {
          /* handle getaddrinfo error */
      }

      /* res->ai_addr contains the network address structure */
      /* ... */
      freeaddrinfo(res);

6.3.  Iterated Jobs for Finding the Working Address

   In a client code, when multiple addresses are returned from
   getaddrinfo(), we should try all of them until connection succeeds.
   When a failure occurs with socket(), connect(), bind(), or some other
   function, the code should go on to try the next address.

   In addition, if something is wrong with the socket call because the
   address family is not supported (i.e., in case of section 4.4),
   applications should try the next address structure.

   Note: In the following examples, the socket() return value error
   handling could be simplified by always continuing on with the socket
   loop instead of performing special checking of specific error
   numbers.

6.3.1.  Example of TCP Server Application

   The previous TCP server example should be written as follows:

      #define MAXSOCK 2
      struct addrinfo hints, *res;
      int error, sockfd[MAXSOCK], nsock=0;

      memset(&hints, 0, sizeof(hints));
      hints.ai_flags = AI_PASSIVE;
      hints.ai_family = AF_UNSPEC;

      hints.ai_socktype = SOCK_STREAM;

      error = getaddrinfo(NULL, SERVICE, &hints, &res);
      if (error != 0) {
          /* handle getaddrinfo error */
      }

      for (aip=res; aip && nsock < MAXSOCK; aip=aip->ai_next) {
          sockfd[nsock] = socket(aip->ai_family,
                                 aip->ai_socktype,
                                 aip->ai_protocol);

          if (sockfd[nsock] < 0) {
              switch errno {
                   case EAFNOSUPPORT:
                   case EPROTONOSUPPORT:
                       /*
                        *  e.g., skip the errors until
                        *  the last address family,
                        *  see section 4.4.
                        */
                        if (aip->ai_next)
                                continue;

                        else {
                               /* handle unknown protocol errors */
                                break;
                        }
                   default:
                        /* handle other socket errors */
                        ;
               }

          } else {
              int on = 1;
              /* optional: works better if dual-binding to wildcard
                 address */
              if (aip->ai_family == AF_INET6) {
                  setsockopt(sockfd[nsock], IPPROTO_IPV6, IPV6_V6ONLY,
                             (char *)&on, sizeof(on));
                  /* errors are ignored */
              }
              if (bind(sockfd[nsock], aip->ai_addr,
                                      aip->ai_addrlen) < 0 ) {
                  /* handle bind error */
                  close(sockfd[nsock]);
                  continue;
              }

              if (listen(sockfd[nsock], SOMAXCONN) < 0) {
                  /* handle listen errors */
                  close(sockfd[nsock]);
                  continue;
              }
          }
          nsock++;
      }
      freeaddrinfo(res);

      /* check that we were able to obtain the sockets */

6.3.2.  Example of TCP Client Application

   The previous TCP client example should be written as follows:

      struct addrinfo hints, *res, *aip;
      int sockfd, error;

      memset(&hints, 0, sizeof(hints));
      hints.ai_family   = AF_UNSPEC;
      hints.ai_socktype = SOCK_STREAM;

      error = getaddrinfo(SERVER_NODE, SERVICE, &hints, &res);
      if (error != 0) {
          /* handle getaddrinfo error */
      }

      for (aip=res; aip; aip=aip->ai_next) {

          sockfd = socket(aip->ai_family,
                          aip->ai_socktype,
                          aip->ai_protocol);

          if (sockfd < 0) {
              switch errno {
                   case EAFNOSUPPORT:
                   case EPROTONOSUPPORT:
                       /*
                        *  e.g., skip the errors until
                        *  the last address family,
                        *  see section 4.4.
                        */
                        if (aip->ai_next)
                                continue;
                        else {
                               /* handle unknown protocol errors */
                                break;

                        }

                   default:
                        /* handle other socket errors */
                        ;
               }

          } else {
              if (connect(sockfd, aip->ai_addr, aip->ai_addrlen) == 0)
                  break;

              /* handle connect errors */
              close(sockfd);
              sockfd=-1;
          }
      }

      if (sockfd > 0) {
          /* socket connected to server address */

          /* ... */
      }

      freeaddrinfo(res);

7.  Transition Mechanism Considerations

   The mechanism [NAT-PT] introduces a special set of addresses, formed
   of an NAT-PT prefix and an IPv4 address these refer to IPv4 addresses
   translated by NAT-PT DNS-ALG.  In some cases, one might be tempted to
   handle these differently.

   However, IPv6 applications must not be required to distinguish
   "normal" and "NAT-PT translated" addresses (or any other kind of
   special addresses, including the IPv4-mapped IPv6 addresses): This
   would be completely impractical, and if the distinction must be made,
   it must be done elsewhere (e.g., kernel, system libraries).

8.  Security Considerations

   There are a number of security considerations for IPv6 transition,
   but those are outside the scope of this memo.

   To ensure the availability and robustness of the service even when
   transitioning to IPv6, this memo describes a number of ways to make
   applications more resistant to failures by cycling through addresses
   until a working one is found.  Doing this properly is critical to
   maintain availability and to avoid loss of service.

   A special consideration about application transition is how IPv4-
   mapped IPv6 addresses are handled.  The use in the API can be seen
   both as a merit (easier application transition) and as a burden
   (difficulty in ensuring whether the use was legitimate).  Note that
   some systems will disable (by default) support for internal IPv4-
   mapped IPv6 addresses.  The security concerns regarding these on the
   wire are legitimate, but disabling it internally breaks one
   transition mechanism for server applications originally written to
   bind() and listen() to a single socket by using a wildcard address
   [V6MAPPED].  This should be considered in more detail when
   applications are designed.

9.  Acknowledgments

   Some of guidelines for development of IP version-independent
   applications (section 6) were first brought up by [AF-APP].  Other
   work to document application porting guidelines has also been in
   progress; for example, [IP-GGF] and [PRT].  We would like to thank
   the members of the v6ops working group and the application area for
   helpful comments.  Special thanks are due to Brian E.  Carpenter,
   Antonio Querubin, Stig Venaas, Chirayu Patel, Jordi Palet, and Jason
   Lin for extensive review of this document.  We acknowledge Ron Pike
   for proofreading the document.

10.  References

10.1.  Normative References

   [RFC3493]   Gilligan, R., Thomson, S., Bound, J., McCann, J., and W.
               Stevens, "Basic Socket Interface Extensions for IPv6",
               RFC 3493, February 2003.

   [RFC3542]   Stevens, W., Thomas, M., Nordmark, E., and T. Jinmei,
               "Advanced Sockets Application Program Interface (API) for
               IPv6", RFC 3542, May 2003.

   [BIS]       Tsuchiya, K., Higuchi, H., and Y. Atarashi, "Dual Stack
               Hosts using the "Bump-In-the-Stack" Technique (BIS)", RFC
               2767, February 2000.

   [BIA]       Lee, S., Shin, M-K., Kim, Y-J., Nordmark, E., and A.
               Durand, "Dual Stack Hosts Using "Bump-in-the-API" (BIA)",
               RFC 3338, October 2002.

   [RFC2460]   Deering, S. and R. Hinden, "Internet Protocol, Version 6
               (IPv6) Specification", RFC 2460, December 1998.

   [RFC3484]   Draves, R., "Default Address Selection for Internet
               Protocol version 6 (IPv6)", RFC 3484, February 2003.

   [RFC3513]   Hinden, R. and S. Deering, "Internet Protocol Version 6
               (IPv6) Addressing Architecture", RFC 3513, April 2003.

10.2.  Informative References

   [2893BIS]   Nordmark, E. and R. E. Gilligan, "Basic Transition
               Mechanisms for IPv6 Hosts and Routers", Work in Progress,
               June 2004.

   [RFC2133]   Gilligan, R., Thomson, S., Bound, J., and W. Stevens,
               "Basic Socket Interface Extensions for IPv6", RFC 2133,
               April 1997.

   [RFC2732]   Hinden, R., Carpenter, B., and L. Masinter, "Format for
               Literal IPv6 Addresses in URL’s", RFC 2732, December
               1999.

   [RFC2821]   Klensin, J., "Simple Mail Transfer Protocol", RFC 2821,
               April 2001.

   [TextRep]   Main, A., "Textual Representation of IPv4 and IPv6
               Addresses", Work in Progress, October 2003.

   [NAT-PT]    Tsirtsis, G. and P. Srisuresh, "Network Address
               Translation - Protocol Translation (NAT-PT)", RFC 2766,
               February 2000.

   [DNSTRANS]  Durand, A. and J. Ihren, "DNS IPv6 Transport Operational
               Guidelines", BCP 91, RFC 3901, September 2004.

   [DNSOPV6]   Durand, A., Ihren, J. and P. Savola, "Operational
               Considerations and Issues with IPv6 DNS", Work in
               Progress, May 2004.

   [AF-APP]    Hagino, J., "Implementing AF-independent application",
               http://www.kame.net/newsletter/19980604/, 2001.

   [V6MAPPED]  Hagino, J., "IPv4 mapped address considered harmful",
               Work in Progress, April 2002.

   [IP-GGF]    Chown, T., Bound, J., Jiang, S. and P. O’Hanlon,
               "Guidelines for IP version independence in GGF
               specifications", Global Grid Forum(GGF) Documentation,
               work in Progress, September 2003.

   [Embed-RP]  Savola, P. and B. Haberman, "Embedding the Rendezvous
               Point (RP) Address in an IPv6 Multicast Address", RFC
               3956, November 2004.

   [RFC3306]   Haberman, B. and D. Thaler, "Unicast-Prefix-based IPv6
               Multicast Addresses", RFC 3306, August 2002.

   [RFC3678]   Thaler, D., Fenner, B., and B. Quinn, "Socket Interface
               Extensions for Multicast Source Filters, RFC 3678,
               January 2004.

   [MUL-GW]    Venaas, S., "An IPv4 - IPv6 multicast gateway", Work in
               Progress, February 2003.

   [PRT]       Castro, E. M., "Programming guidelines on transition to
               IPv6 LONG project", Work in Progress, January 2003.

Appendix A.  Other Binary/Presentation Format Conversions

   Section 6.2.3 describes the preferred way to perform
   binary/presentation format conversions; these can also be done by
   using inet_pton() and inet_ntop() and by writing protocol-dependent
   code.  This approach is not recommended, but it is provided here for
   reference and comparison.

   Note that inet_ntop()/inet_pton() lose the scope identifier (if used,
   e.g., with link-local addresses) in the conversions, contrary to the
   getaddrinfo()/getnameinfo() functions.

A.1.  Binary to Presentation Using inet_ntop()

   Conversions from network address structure to presentation format can
   be written as follows:

      struct sockaddr_storage ss;
      char addrStr[INET6_ADDRSTRLEN];

      /* fill ss structure */

      switch (ss.ss_family) {

           case AF_INET:
                inet_ntop(ss.ss_family,
                         &((struct sockaddr_in *)&ss)->sin_addr,
                         addrStr,
                         sizeof(addrStr));
                break;

           case AF_INET6:
                inet_ntop(ss.ss_family,
                          &((struct sockaddr_in6 *)&ss)->sin6_addr,
                          addrStr,
                          sizeof(addrStr));

                break;

           default:
                /* handle unknown family */
      }

   Note that, the destination buffer addrStr should be long enough to
   contain the presentation address format: INET_ADDRSTRLEN for IPv4 and
   INET6_ADDRSTRLEN for IPv6.  As INET6_ADDRSTRLEN is longer than
   INET_ADDRSTRLEN, the first one is used as the destination buffer
   length.

A.2.  Presentation to Binary Using inet_pton()

   Conversions from presentation format to network address structure can
   be written as follows:

      struct sockaddr_storage ss;
      struct sockaddr_in *sin;
      struct sockaddr_in6 *sin6;
      char addrStr[INET6_ADDRSTRLEN];

      /* fill addrStr buffer and ss.ss_family */

      switch (ss.ss_family) {
            case AF_INET:
                  sin = (struct sockaddr_in *)&ss;
                  inet_pton(ss.ss_family,
                            addrStr,
                            (sockaddr *)&sin->sin_addr));
                  break;

            case AF_INET6:
                  sin6 = (struct sockaddr_in6 *)&ss;
                  inet_pton(ss.ss_family,
                            addrStr,
                            (sockaddr *)&sin6->sin6_addr);
                  break;

            default:
                /* handle unknown family */
      }

   Note that, the address family of the presentation format must be
   known.

Authors’ Addresses

   Myung-Ki Shin
   ETRI/NIST
   820 West Diamond Avenue
   Gaithersburg, MD 20899, USA

   Phone: +1 301 975-3613
   Fax:   +1 301 590-0932
   EMail: mshin@nist.gov

   Yong-Guen Hong
   ETRI PEC
   161 Gajeong-Dong, Yuseong-Gu, Daejeon 305-350, Korea

   Phone: +82 42 860 6447
   Fax:   +82 42 861 5404
   EMail: yghong@pec.etri.re.kr

   Jun-ichiro itojun HAGINO
   Research Laboratory, Internet Initiative Japan Inc.
   Takebashi Yasuda Bldg.,
   3-13 Kanda Nishiki-cho,
   Chiyoda-ku,Tokyo 101-0054, JAPAN

   Phone: +81-3-5259-6350
   Fax:   +81-3-5259-6351
   EMail: itojun@iijlab.net

   Pekka Savola
   CSC/FUNET
   Espoo, Finland

   EMail: psavola@funet.fi

   Eva M. Castro
   Rey Juan Carlos University (URJC)
   Departamento de Informatica, Estadistica y Telematica
   C/Tulipan s/n
   28933 Madrid - SPAIN

   EMail: eva@gsyc.escet.urjc.es

Full Copyright Statement

   Copyright (C) The Internet Society (2005).

   This document is subject to the rights, licenses and restrictions
   contained in BCP 78, and except as set forth therein, the authors
   retain all their rights.

   This document and the information contained herein are provided on an
   "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
   OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
   ENGINEERING TASK FORCE DISCLAIM 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.

Intellectual Property

   The IETF takes no position regarding the validity or scope of any
   Intellectual Property Rights or other rights that might be claimed to
   pertain to the implementation or use of the technology described in
   this document or the extent to which any license under such rights
   might or might not be available; nor does it represent that it has
   made any independent effort to identify any such rights.  Information
   on the procedures with respect to rights in RFC documents can be
   found in BCP 78 and BCP 79.

   Copies of IPR disclosures made to the IETF Secretariat and any
   assurances of licenses to be made available, or the result of an
   attempt made to obtain a general license or permission for the use of
   such proprietary rights by implementers or users of this
   specification can be obtained from the IETF on-line IPR repository at
   http://www.ietf.org/ipr.

   The IETF invites any interested party to bring to its attention any
   copyrights, patents or patent applications, or other proprietary
   rights that may cover technology that may be required to implement
   this standard.  Please address the information to the IETF at ietf-
   ipr@ietf.org.

Acknowledgement

   Funding for the RFC Editor function is currently provided by the
   Internet Society.
------分隔线----------------------------
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
最新评论 查看所有评论
发表评论 查看所有评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 密码: 验证码:
推荐内容