# Compaq TCP/IP Services for OpenVMS
Guide to IPv6

Previous | Contents

## 5.5.3 On-Link Node Is Unreachable

If an on-link node is not reachable, one of the following messages can appear:

    host is unreachable
    network is unreachable
    timeout

Verify that an on-link node or router is reachable by using the `ping` command. If the command fails or if packets are frequently dropped, complete the following steps:

1. If the node is attached to a LAN, check the data link counters by using the LANCP SHO DEVICE device /COUNTERS command. Problems with the counters and their possible causes are as follows:
   - Zero blocks sent or received can indicate a network hardware failure or a wiring problem.
   - High collision rates can indicate an improperly wired network or a node that is sending excessive message traffic.
   - Data overrun and buffer unavailable errors indicate your system is misconfigured.
2. If the data link counters are okay, check the IPv6 and ICMPv6 counters with the `netstat -p ipv6` and `netstat -p ipv6 -icmp` commands, respectively. Problems with the counters and their possible causes are as follows:
   - Packets discarded because of errors, or errors resulting from ICMP errors, indicate that another node is generating invalid messages. Other counters show more specific information.
   - Allocation errors can indicate excessive message traffic, a misconfigured system, or a program that repeatedly allocates memory without freeing it.
3. Verify that IPv6 network interfaces exist, are up, and have `inet6` addresses by using the `ifconfig -a` command. If they do not have `inet6` addresses, check the configuration file TCPIP$INET6_CONFIG.DAT. Run the TCPIP$IP6_SETUP utility to correct any errors.
4. Contact the system administrator for the adjacent on-link node and verify that the on-link node is up and running, that it is configured correctly for IPv6, and that the address you are using is enabled on the node's interface.
5. If IPv4 is configured on both systems, issue the `ping` command to the on-link node's IPv4 address. If the command succeeds, verify the IPv6 configuration on both systems. If the command fails, see the appropriate troubleshooting manuals.
6. Issue the `ping` command to other nodes on the link to determine whether the failure is confined to one node or whether it extends to multiple nodes. Partial connectivity might indicate a faulty network device or cable on the link.
7. If the link is a configured tunnel, do the following:
   1. Verify the tunnel source and destination addresses by using the `ifconfig -a` command. Contact the administrator for the tunnel destination node and verify that your source and destination addresses match the destination and source addresses on that node.
   2. Issue the `ping` command to the tunnel destination address. If the command fails, see the Compaq TCP/IP Services for OpenVMS Management guide for more information.

## 5.5.4 Off-Link Node Is Unreachable

If an off-link node is not reachable, the following messages appear:

    host is unreachable
    network is unreachable
    timeout

Verify that an off-link node is reachable by issuing the `ping` command.

If there is 100% packet loss, perform the following steps:

1. Verify connectivity between your system and an on-link router by using the `ping` command.
   If the command fails or shows frequently dropped packets, follow the steps in Section 5.5.3.
2. Verify that the interface over which you are sending messages has a global or site-local unicast address enabled by using the `ifconfig -a` command.
   If it does not, check the prefixes defined in the SYS$SYSTEM:TCPIP$IP6RTRD.CONF file. Run the TCPIP$IP6_SETUP utility to correct any errors.
3. Contact the administrator for the remote system to verify that the system is up and running, that it is configured correctly for IPv6, and that the IPv6 address on its interface is the same as the address you are using.
   If the address is different, check your system's TCPIP$ETC:TCPIP$IPNODES.DAT file, or have the remote system administrator check the DNS entry.
4. Verify that there is a default route (with `U` and `G` flags set) to a router on the network by issuing the `netstat -rf inet6` command.
   If the route is missing or incorrect, check the routes and the address prefixes in the SYS$SYSTEM:TCPIP$IP6RTRD.CONF file.
   If your site uses RIPng, verify that RIP is enabled in the SYS$SYSTEM:TCPIP$IP6RTRD.CONF file. If it is, contact the administrator of the next router to verify that RIP is enabled.
5. Trace the path to the off-link node by using the `traceroute` command.

Frequently dropped packets indicate either network congestion or an intermittent routing problem.

To determine the cause, do the following:

1. Verify connectivity between your system and an on-link router by using the `ping` command.
2. Trace the path to the off-link node by using the `traceroute` command.

## 5.5.5 On-Link Node Addresses Are Not Configured

IPv6 hosts generate their global and site-local unicast addresses automatically by using address prefixes provided by a router on the link. If an on-link node cannot autoconfigure its addresses, perform the following steps:

1. Verify that the host is reachable from your router by using the `ping` command and specifying the host's link-local address. If the command fails or shows a high rate of packet loss, follow the steps in Section 5.5.3.
2. Edit the SYS$SYSTEM:TCPIP$IP6RTRD.CONF file and verify that the router is configured to advertise the correct prefixes and that the timers are reasonable. See Chapter 2 and Appendix B for more information.

## 5.5.6 Router Does Not Forward Messages

If another network user reports that message transmission appears to be failing at your router, perform the following steps:

1. Obtain the source and destination addresses of the message that your router is not forwarding. Then verify that your router can reach each node by using the `ping` command.
   If the command fails or shows a high rate of packet loss, follow the steps in Section 5.5.3 for on-link nodes, or in Section 5.5.4 for off-link nodes.
2. If your router is running the RIPng protocol, verify that the IPv6 router process is running by issuing the following command:

       $ SHO SYS /PROCESS=TCPIP$IP6RTRD

   If the process is running, edit the SYS$SYSTEM:TCPIP$IP6RTRD.CONF file and verify that the RIPng protocol is enabled on each IPv6 link. If it is not, your node may not be propagating routes correctly.
3. Make sure that you are not using manual routes on some interfaces and RIPng routes on other interfaces. Manual routes defined in the TCPIP$ROUTE.DAT file do not get propagated to other routers with RIPng.

## 5.5.7 Your Node Is Unreachable

If someone reports a problem reaching your node from another node, perform the following steps:

1. Verify that their node is reachable by issuing the `ping` command.
   If the command fails, follow the steps in Section 5.5.3 for an on-link node, or Section 5.5.4 for an off-link nodes.
2. If they are using a name from the DNS database, verify that the address for your node in the DNS database matches one of the addresses configured on your system's interfaces.
   Use the `nslookup -type=AAAA node-name` command to retrieve the address from DNS; use the `ifconfig -a` command to display addresses for your system.
3. If they are using an address defined in their local host file, compare that address with the addresses configured on your system's interfaces by using the `ifconfig -a` command.

## 5.5.8 Connection Is Not Accepted

If a remote node is not configured to accept a connection from your application, the following message might appear:

    connection refused

Verify that TCP/IP Services has been correctly configured on the remote node to accept connections.

Contact the administrator for the remote node and ask whether the correct socket-based service definitions are defined in the TCPIP$SERVICES.DAT file. Check whether the service has IPv6 enabled.

## 5.5.9 Connection Terminates

If the connection terminates abnormally or if a network application appears to hang, perform the following steps:

1. Verify that there is network connectivity to the remote node by using the `ping` command immediately after the failure.
   If the `ping` command fails or shows a high rate of packet loss, follow the steps in Section 5.5.3 for an on_link node, or in Section 5.5.4 for an off-link node.
2. If your application transfers a large amount of data over the network, verify that large or fragmented messages are being handled correctly by using the `ping -s 2000 nodename` command.
   If the `ping` command fails, trace the path to the remote node with 1200-byte packets by using the `traceroute nodename 1200` command. All IPv6 links should support message sizes of at least 1280 bytes. This command might show the location of the problem in the network.
3. Run the application with different client and server nodes located on different links in the network.

# Chapter 6
Application Interface to Sockets

The TCP/IP Services for OpenVMS programming interface supports the Berkeley Software Distribution (BSD) socket programming interface. It also supports the basic sockets interface extensions for Internet Protocol Version 6 (IPv6) as defined in RFC 2553. The basic syntax of socket functions remains the same. Existing IPv4 applications will continue to operate as before, and IPv6 applications can interoperate with IPv4 applications.

TCP/IP Services for OpenVMS provides Internet domain support for the address family AF_INET and AF_INET6.

This chapter describes the following aspects of the API:

- Socket interface
- Interface identification
- IPv6 multicast datagrams
- Socket options
- Library functions
- Guidelines for compiling and linking

# 6.1 Socket Interface

The IPv6 socket interface incorporates the following changes:

- New address family: AF_INET6
- New protocol family: PF_INET6
- New address structure: `in6_addr`

         struct in6_addr {
                uint8_t s6_addr[16]:
           }

  The address is stored in network byte order as an array of sixteen 8-bit elements.
- Revised socket address structure: `sockaddr_in6`
  If the _SOCKADDR_LEN symbol is defined in an application, the following BSD Version 4.4 structure is used:

       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;
           };

  Note BSD Version 4.3 will be supported in a subsequent release.

- New wildcard address, defined in network byte order. The address has the following forms:
  - A global variable, `in6addr_any` , that is an `in6_addr` structure.
  - A symbolic constant, IN6ADDR_ANY_INIT, that can be used to initialize an `in6_addr` structure only when it is declared.
- New loopback address, defined in network byte order. The address has the following forms:
  - A global variable, `in6addr_loopback` , that is an `in6_addr` structure.
  - A symbolic constant, IN6ADDR_LOOPBACK_INIT, that can be used to initialize an `in6_addr` structure only when it is declared.

The basic syntax of socket functions remains the same. Existing IPv4 applications will continue to operate as before. IPv6 applications can interoperate with IPv4 applications.

# 6.2 Interface Identification

To identify the interface on which a datagram is received, on which a datagram is to be sent, and on which a multicast group is joined, the API uses a small, positive integer called an interface index. The kernel assigns this integer to an interface when the interface is initialized.

The API defines the following new functions:

Function | Description
--- | ---
`if_nametoindex` | Maps an interface name to its corresponding index.
`if_indextoname` | Maps an interface index to its corresponding name.
`if_nameindex` | Returns an array of all interface names and indexes.
`if_freenameindex` | Frees dynamic memory allocated by `if_nameindex` to the array of interface names and indexes.

## 6.2.1 if_nametoindex Function

The `if_nametoindex` function has the following syntax:

    #include <net/if.h>

    unsigned int if_nametoindex(
            const char *ifname );

If the interface does not exist, the function returns 0 and sets `errno` to ENXIO. If a system error occurs, the function returns 0 and sets `errno` to an appropriate value.

## 6.2.2 if_indextoname Function

The `if_indextoname` function has the following syntax:

    #include <net/if.h>

    char *if_indextoname(
            unsigned int ifindex,
            char *ifname );

The ifname argument points to a buffer that is IFNAMSIZ bytes in length (IFNAMSIZ is defined in TCPIP$EXAMPLES:IF.H). If an interface name is found, it is returned in the buffer. If no interface name corresponds to the specified index, the function returns NULL and sets `errno` to ENXIO. If a system error occurs, the function returns NULL and sets `errno` to an appropriate value.

## 6.2.3 if_nameindex Function

The `if_nameindex` function has the following syntax:

    #include <net/if.h>
    struct if_nameindex *if_nameindex( void );

The following `if_nameindex` structure must also be defined (by including (TCPIP$EXAMPLES:IF.H) prior to the call to `if_nameindex` :

    struct if_nameindex {
       unsigned int   if_index;
       char           *if_name;
    };

The `if_nameindex` function dynamically allocates memory for an array of `if_nameindex` structures, one structure for each interface. A structure with an `if_index` value of 0 and a NULL `if_name` value indicates the end of the array. If an error occurs, the function returns a NULL pointer and sets `errno` to an appropriate value. To free the memory allocated by this function, use the `if_freenameindex` function.

## 6.2.4 if_freenameindex Function

The `if_freenameindex` function has the following syntax:

    #include <net/if.h>

    void if_freenameindex(
            struct if_nameindex *ptr );

The `if_freenameindex` function frees dynamic memory that was allocated by the `if_nameindex` function. The argument to this function is the pointer that was returned by the `if_nameindex` function.

# 6.3 IPv6 Multicast Datagrams

## 6.3.1 Sending IPv6 Multicast Datagrams

To send IPv6 multicast datagrams, an application indicates the multicast group to send to by specifying an IPv6 multicast address in a `sendto` system call. The system maps the specified IPv6 destination address to the appropriate Ethernet or FDDI multicast address prior to transmitting the datagram.

An application can explicitly control multicast options with arguments to the `setsockopt` system call. The following options can be set by an application using the `setsockopt` system call:

- Hop limit (IPV6_MULTICAST_HOPS)
- Multicast interface (IPV6_MULTICAST_IF)
- Disabling loopback of local delivery (IPV6_MULTICAST_LOOP)

Note The examples here illustrate how to use the `setsockopt` options that apply to IPv6 multicast datagrams only.

The IPV6_MULTICAST_HOPS option to the `setsockopt` system call allows an application to specify a value between 0 and 255 for the hop limit field.

Multicast datagrams with a hop limit value of 0 restrict distribution of the multicast datagram to applications running on the local host. Multicast datagrams with a hop limit value of 1 are forwarded only to hosts on the local link. If a multicast datagram has a hop limit value greater than 1 and a multicast router is attached to the sending host's network, multicast datagrams can be forwarded beyond the local link. Multicast routers forward the datagram to known networks that have hosts belonging to the specified multicast group. The hop limit value is decremented by each multicast router in the path. When the hop limit value is decremented to 0, the datagram is not forwarded further.

The following example shows how to use the IPV6_MULTICAST_HOPS option to the `setsockopt` system call:

    u_char hops;
    hops=2;

    if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops,
                         sizeof(hops)) < 0)
                         perror("setsockopt: IPV6_MULTICAST_HOPS error");

A datagram addressed to an IPv6 multicast address is transmitted from the default network interface unless the application specifies that an alternate network interface is associated with the socket. The default interface is determined by the interface associated with the default route in the kernel routing table or by the interface associated with an explicit route, if one exists. Using the IPV6_MULTICAST_IF option to the `setsockopt` system call, an application can specify a network interface other than that specified by the route in the kernel routing table.

The following example shows how to use the IPV6_MULTICAST_IF option to the `setsockopt` system call to specify an interface other than the default:

    u_int if_index = 1;
    .
    .
    .
    if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, &if_index,
                                  sizeof(if_index)) < 0)
         perror ("setsockopt: IPV6_MULTICAST_IF error");
      else
         printf ("new interface set for sending multicast datagrams\n");

The if_index parameter specifies the interface index of the desired interface, or specifies 0 to select a default interface. You can use the `if_nametoindex` routine to find the interface index.

If a multicast datagram is sent to a group that has the sending node is a member, a copy of the datagram is, by default, looped back by the IP layer for local delivery. The IPV6_MULTICAST_LOOP option to the `setsockopt` system call allows an application to disable this loopback delivery.

The following example shows how to use the IPV6_MULTICAST_LOOP option to the `setsockopt` system call:

    u_char loop=0;
    if (setsockopt( sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &loop,
             sizeof(loop)) < 0)
             perror("setsockopt: IPV6_MULTICAST_LOOP error");

If the value of loop is 0, loopback is disabled; if the value of loop is 1, loopback is enabled. For performance reasons, you should disable the default, unless applications on the same host must receive copies of the datagrams.

## 6.3.2 Receiving IPv6 Multicast Datagrams

Before a node can receive IPv6 multicast datagrams destined for a particular multicast group other than the All Nodes group, an application must direct the node to become a member of that multicast group.

This section describes how an application can direct a node to add itself to and remove itself from a multicast group.

An application can direct the node it is running on to join a multicast group by using the IPV6_JOIN_GROUP option to the `setsockopt` system call:

    struct ipv6_mreq imr6;
    .
    .
    .
    imr6.ipv6mr_interface = if_index;
    if (setsockopt( sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
         (char *)&imr6, sizeof(imr6)) < 0)
         perror("setsockopt: IPV6_JOIN_GROUP error");

The imr6 parameter has the following structure:

    structipv6_mreq {
            struct in6_addr ipv6mr_multiaddr; /* IP multicast address of
    group */
            unsigned int ipv6mr_interface; /* local interface index*/
            };

Each multicast group membership is associated with a particular interface. It is possible to join the same group on multiple interfaces. The ipv6mr_interface variable can be specified with a value of 0, which allows an application to choose the default multicast interface. Alternatively, specifying one of the host's local interfaces allows an application to select a particular multicast-capable interface. The maximum number of memberships that can be added on a single socket is subject to the IPV6_MAX_MEMBERSHIPS value, which is defined in the `<netinet/in.h>` header file.

To drop membership from a particular multicast group, use the IPV6_LEAVE_GROUP option to the `setsockopt` system call:

    struct ipv6_mreq imr6;
    if (setsockopt( sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &imr6,
         sizeof(imr6)) < 0)
         perror("setsockopt: IPV6_LEAVE_GROUP error");

The imr6 parameter contains the same structure values used for adding membership.

If multiple sockets request that a node join a particular multicast group, the node remains a member of that multicast group until the last of those sockets is closed.

To receive multicast datagrams sent to a specific UDP port, the receiving socket must have bound to that port using the `bind` system call. More than one process can receive UDP datagrams destined for the same port if the `bind` system call is preceded by a `setsockopt` system call that specifies the SO_REUSEPORT option.

Delivery of IP multicast datagrams to SOCK_RAW sockets is determined by the protocol type of the destination.

Previous | Next | Contents