|
|
Due to the increased size of the IPv6 address, two new structures are needed. These structures are:
The in6_addr structure holds a single IPv6 address. The structure is shown below.
struct in6_addr { u_int8_t s6_addr[16]; /* IPv6 address */ }The structure contains an array of sixteen 8-bit elements, that together make up a single 128-bit IPv6 address. The address is usually stored in network byte order.
This structure is declared in netinet/in.h.
The sockaddr_in6 structure is used to pass address information to the socket function calls that require network address information. The structure is shown below.
# define SIN6_LENstruct sockaddr_in6 { u_char sin6_len; /* length of this structure */ u_char sin6_family; /* AF_INET6 */ u_int16m_t sin6_port; /* Transport layer port # */ u_int32m_t sin6_flowinfo; /* IPv6 flow information */ struct in6_addr sin6_addr; /* IPv6 address */ };
sin6_family
member has been changed from a
16-bit to an 8-bit data type. This change has also been effected in the
sockaddr_in data structure. Binaries built using the older data
structures will still work, however, new applications will use the newer
version of sockaddr_in (for IPv4 applications) or
sockaddr_in6 (for IPv6 applications).
When allocating a buffer to hold the sockaddr_in6 structure always use sizeof(struct sockaddr_in6) because the sockaddr_in6 structure is larger than sockaddr.
In IPv4 two constants, INADDR_ANY and INADDR_LOOPBACK, are provided for system selection of source addresses and loopback. In IPv6, because the address is stored in the in6_addr structure, a different mechanism has to be used as described below.
To enable the system to select the source address for your IPv6 application, use the global variable in6addr_any. For example, to bind to port number 23, and let the system select the source address, you could use the following code:
struct sockaddr_in6 sin6; ... sin6.sin6_len = sizeof(sin6); sin6.sin6_family = AF_INET6; sin6.sin6_flowinfo = 0; sin6.sin6_port = htons(23); sin6.sin6_addr = in6addr_any; ... if (bind(s, (struct sockaddr *) &sin6, sizeof(sin6)) == -1) { ... }If you just want to initialize a in6_addr structure, you can use the symbolic constant IN6ADDR_ANY_INIT as shown in the code below.
struct in6_addr anyaddr = IN6ADDR_ANY_INIT;
struct sockaddr_in6 sin6; ... sin6.sin6_addr = INADDR_ANY_INIT;
INADDR_ANY_INIT and in6addr_any are declared in netinet/in.h.
To enable your application to use local UDP and TCP services, use the global variable in6addr_loopback. For example, to open a TCP connection to the local telnet server, you could use the following code:
struct sockaddr_in6 sin6; ... sin6.sin6_len = sizeof(sin6); sin6.sin6_family = AF_INET6; sin6.sin6_flowinfo = 0; sin6.sin6_port = htons(23); sin6.sin6_addr = in6addr_loopback; ... if (bind(s, (struct sockaddr *) &sin6, sizeof(sin6)) == -1) { ... }If you just want to initialize a in6_addr structure, you can use the symbolic constant IN6ADDR_LOOPBACK_INIT as shown in the code below.
struct in6_addr anyaddr = IN6ADDR_LOOPBACK_INIT;
struct sockaddr_in6 sin6; ... sin6.sin6_addr = INADDR_LOOPBACK_INIT;
INADDR_LOOPBACK_INIT and in6addr_loopback are declared in netinet/in.h.