INET6

Internet protocol version 6 family

Synopsis:

#include <netinet/in.h>

struct sockaddr_in6 {
    uint8_t sin6_len;
    sa_family_t sin6_family;
    in_port_t sin6_port;
    uint32_t sin6_flowinfo;
    struct in6_addr sin6_addr;
    uint32_t sin6_scope_id;
};

Description:

Protocols

The INET6 family consists of the:

  • IPv6 network protocol
  • Internet Control Message Protocol version 6 (ICMP)
  • Transmission Control Protocol (TCP)
  • User Datagram Protocol (UDP).

TCP supports the SOCK_STREAM abstraction, while UDP supports the SOCK_DGRAM abstraction. Note that TCP and UDP are common to INET and INET6. A raw interface to IPv6 is available by creating an Internet SOCK_RAW socket. The ICMPv6 message protocol may be accessed from a raw socket.

The INET6 protocol family is an updated version of the INET family. While INET implements Internet Protocol version 4, INET6 implements Internet Protocol version 6.

Addressing

IPv6 addresses are 16-byte quantities, stored in network standard (big-endian) byte order. The header file <netinet/in.h> defines this address as a discriminated union.

Sockets bound to the INET6 family use the structure shown above.

You can create sockets with the local address :: (which is equal to IPv6 address 0:0:0:0:0:0:0:0) to cause "wildcard" matching on incoming messages. You can specify the address in a call to connect() or sendto() as :: to mean the local host. You can get the :: value by setting the sin6_addr field to 0, or by using the address contained in the in6addr_any global variable, which is declared in <netinet6/in6.h>.

The IPv6 specification defines scoped addresses, such as link-local or site-local addresses. A scoped address is ambiguous to the kernel if it's specified without a scope identifier. To manipulate scoped addresses properly in your application, use the advanced API defined in RFC 2292. A compact description on the advanced API is available in IP6. If you specify scoped addresses without an explicit scope, the socket manager may return an error.

Scoped addresses are currently experimental, from both a specification and an implementation point of view.

The KAME implementation supports extended numeric IPv6 address notation for link-local addresses. For example, you can use fe80::1%de0 to specify "fe80::1 on the de0 interface." The getaddrinfo() and getnameinfo() functions support this notation. With special programs like ping6 , you can disambiguate scoped addresses by specifying the outgoing interface with extra command-line options.

The socket manager handles scoped addresses in a special manner. In the socket manager's routing tables or interface structures, a scoped address's interface index is embedded in the address. Therefore, the address contained in some of the socket manager structures isn't the same as on the wire. The embedded index becomes visible when using the PF_ROUTE socket or the sysctl() function. You shouldn't use the embedded form.

Interaction between IPv4/v6 sockets

The behavior of the AF_INET6 TCP/UDP socket is documented in the RFC 2553 specification, which states:

  • A specific bind on an AF_INET6 socket ( bind() with an address specified) should accept IPv6 traffic to that address only.
  • If you perform a wildcard bind on an AF_INET6 socket ( bind() to the IPv6 address ::), and there isn't a wildcard-bound AF_INET socket on that TCP/UDP port, then the IPv6 traffic as well as the IPv4 traffic should be routed to that AF_INET6 socket. IPv4 traffic should be seen by the application as if it came from an IPv6 address such as ::ffff:10.1.1.1. This is called an IPv4 mapped address.
  • If there are both wildcard-bound AF_INET sockets and wildcard-bound AF_INET6 sockets on one TCP/UDP port, they should operate independently: IPv4 traffic should be routed to the AF_INET socket, and IPv6 should be routed to the AF_INET6 socket.

However, the RFC 2553 specification doesn't define the constraint between the binding order, nor how the IPv4 TCP/UDP port numbers and the IPv6 TCP/UDP port numbers relate each other (whether they must be integrated or separated). The behavior is very different from implementation to implementation. It is unwise to rely too much on the behavior of the AF_INET6 wildcard-bound socket. Instead, connect to two sockets, one for AF_INET and another for AF_INET6, when you want to accept both IPv4 and IPv6 traffic.

Use caution when handling connections from IPv4 mapped addresses with AF_INET6 sockets—if the target node routes IPv4 traffic to AF_INET6 sockets, malicious parties can bypass security.

Because of the security hole, by default, NetBSD doesn't route IPv4 traffic to AF_INET6 sockets. If you want to accept both IPv4 and IPv6 traffic, use two sockets. IPv4 traffic may be routed with multiple per-socket/per-node configurations, but, it isn't recommended. See IP6 for details.

The IPv6 support is subject to change as the Internet protocols develop. Don't depend on details of the current implementation, but rather the services exported. Try to implement version-independent code as much as possible, because you'll need to support both INET and INET6.

Based on:

RFC 2553, RFC 2292

Last modified: 2013-12-21

comments powered by Disqus