⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rfc2553.txt

📁 RFC 的详细文档!
💻 TXT
📖 第 1 页 / 共 5 页
字号:
   is defined in <netinet/in.h>.  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 <netinet/in.h>:

      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 <netinet/in.h>.  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 <net/if.h>

      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 <net/if.h>

      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 <net/if.h> 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 <net/if.h>
   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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -