# Compaq TCP/IP Services for OpenVMS
Guide to IPv6

Previous | Contents

### 6.5.3.2 inet_ntop Function

This function has the following syntax:

    const char *inet_ntop(
                      int af,
                      const void *src,
                      char *dst,
                      size_t size);

Parameters

- af
  Specifies the address family. Valid values are AF_INET for an IPv4 address and AF_INET6 for an IPv6 address.
- src
  Points to a buffer that contains the numeric Internet address.
- dst
  Points to a buffer that is to contain the text string.
- size
  Specifies the size of the buffer pointed to by the dst parameter. For IPv4 addresses, the minimum buffer size is 16 octets; for IPv6 addresses, the minimum buffer size is 46 octets. The `<netinet/in.h>` header file defines the INET_ADDRSTRLEN and INET6_ADDRSTRLEN constants, respectively, for these values.

Description

The `inet_ntop()` function converts a numeric Internet address value to a text string.

Return values

Upon successful conversion, the `inet_ntop()` function returns a pointer to the buffer containing the text string. If the function fails, it returns a pointer to the buffer containing NULL.

## 6.5.4 Address-Testing Macros

Table 6-3 lists the currently defined address-testing macros and the return value for a valid test. To use these macros, include the following file in your application:

    #include <net/in.h>

Table 6-3 Summary of Address-Testing Macros
Macro | Return
--- | ---
IN6_IS_ADDR_UNSPECIFIED | True, if specified type.
IN6_IS_ADDR_LOOPBACK | True, if specified type.
IN6_IS_ADDR_MULTICAST | True, if specified type.
IN6_IS_ADDR_LINKLOCAL | True, if specified type.
IN6_IS_ADDR_SITELOCAL | True, if specified type.
IN6_IS_ADDR_V4MAPPED | True, if specified type.
IN6_IS_ADDR_V4COMPAT | True, if specified type.
IN6_IS_ADDR_MC_NODELOCAL | True, if specified scope.
IN6_IS_ADDR_MC_LINKLOCAL | True, if specified scope.
IN6_IS_ADDR_MC_SITELOCAL | True, if specified scope.
IN6_IS_ADDR_MC_ORGLOCAL | True, if specified scope.
IN6_IS_ADDR_MC_GLOBAL | True, if specified scope.
IN6_ARE_ADDR_EQUAL | True, if addresses are equal.

# 6.6 Guidelines for Compiling and Linking IPv6 Applications

To compile an IPv6 application, you need to set up the following environment:

    $ DEFINE DECC$SYSTEM_INCLUDE TCPIP$EXAMPLES:
    $ DEFINE ARPA TCPIP$EXAMPLES:
    $ DEFINE NET TCPIP$EXAMPLES:
    $ DEFINE NETINET TCPIP$EXAMPLES:
    $ DEFINE SYS TCPIP$EXAMPLES:

This is a temporary measure and is required until Compaq C has all the IPv6 include files.

The library functions described in this chapter are included in the Compaq TCP/IP Services for OpenVMS Version 5.1 kit.

# Chapter 7
Porting Applications

This chapter describes the changes you must make in your application code to operate in an IPv6 networking environment.

- Name changes
- Structure changes
- Other changes

You can also use this information as guidelines for creating new IPv6-ready applications.

See RFC 2553, Basic Socket Interface Extensions for IPv6, for complete information on the changes to the BSD socket applications programming interface (API). 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.

# 7.1 Using AF_INET6 Sockets

At present, applications use AF_INET sockets for IPv4 communications. Figure 7-1 shows a sample sequence of events for an application that uses an AF_INET socket to send IPv4 packets.

Figure 7-1 Using AF_INET Socket for IPv4 Communications

1. Application calls `gethostbyname` and passes the host name, host1.
2. The search finds host1 in the hosts database and `gethostbyname` returns the IPv4 address 1.2.3.4.
3. The application opens an AF_INET socket.
4. The application sends information to the 1.2.3.4 address.
5. The socket layer passes the information and address to the UDP module.
6. The UDP module puts the 1.2.3.4 address into the packet header and passes the information to the IPv4 module for transmission.

Section 7.6.1.1 contains sample program code that demonstrates these steps.

You can use the AF_INET6 socket for both IPv6 and IPv4 communications. For IPv4 communications, create an AF_INET6 socket and pass it a `sockaddr_in6` structure that contains an IPv4-mapped IPv6 address (for example, `::ffff:1.2.3.4` ). Figure 7-2 shows the sequence of events for an application that uses an AF_INET6 socket to send IPv4 packets.

Figure 7-2 Using AF_INET6 Socket to Send IPv4 Communications

1. Application calls `getaddrinfo` and passes the host name (host1), the AF_INET6 address family hint, and the AI_DEFAULT flag hint. The flag tells the function that if an IPv4 address is found for host1, return the address as an IPv4-mapped IPv6 address.
2. The search finds an IPv4 address, 1.2.3.4, for host1 in the hosts database and `getaddrinfo` returns the IPv4-mapped IPv6 address `::ffff:1.2.3.4` .
3. The application opens an AF_INET6 socket.
4. The application sends information to the `::ffff:1.2.3.4` address.
5. The socket layer passes the information and address to the UDP module.
6. The UDP module identifies the IPv4-mapped IPv6 address, puts the 1.2.3.4 address into the packet header, and passes the information to the IPv4 module for transmission.

AF_INET6 sockets can receive messages sent to either IPv4 or IPv6 addresses on the system. An AF_INET6 socket uses the IPv4-mapped IPv6 address format to represent IPv4 addresses. Figure 7-3 shows the sequence of events for an application that uses an AF_INET6 socket to receive IPv4 packets.

Figure 7-3 Using AF_INET6 Socket to Receive IPv4 Communications

1. The application opens an AF_INET6 socket, binds to it, and listens on it.
2. An IPv4 packet arrives and passes through the IPv4 module.
3. The TCP layer strips off the packet header and passes the information and the IPv4-mapped IPv6 address `::ffff:1.2.3.4` to the socket layer.
4. The application calls `accept` and retrieves the information from the socket.
5. The application calls `getnameinfo` and passes the `::ffff:1.2.3.4` address and the NI_NAMEREQD flag. The flag tells the function to return the host name for the address. See Table 6-2 for a description of the flag bits and their meanings.
6. The search finds the host name for the 1.2.3.4 address in the hosts database, and `getnameinfo` returns the host name.

For IPv6 communications, create an AF_INET6 socket and pass it a `sockaddr_in6` structure that contains an IPv6 address (for example, `3ffe:1200::a00:2bff:fe2d:02b2` ). Figure 7-4 shows the sequence of events for an application that uses an AF_INET6 socket to send IPv6 packets.

Figure 7-4 Using AF_INET6 Socket for IPv6 Communications

1. Application calls `getaddrinfo` and passes the host name (host1), the AF_INET6 address family hint, and the AI_DEFAULT flag hint. The flag tells the function that if an IPv4 address is found for host1, to return it.
2. The search finds an IPv6 address for host1 in the hosts database, and `getaddrinfo` returns the IPv6 address `3ffe:1200::a00:2bff:fe2d:02b2` .
3. The application opens an AF_INET6 socket.
4. The application sends information to the `3ffe:1200::a00:2bff:fe2d:02b2` address.
5. The socket layer passes the information and address to the UDP module.
6. The UDP module identifies the IPv6 address and puts the `3ffe:1200::a00:2bff:fe2d:02b2` address into the packet header and passes the information to the IPv6 module for transmission.

Section 7.6.2.1 contains sample program code that demonstrates these steps.

The following sections show how to convert an existing AF_INET application to an AF_INET6 application that is capable of communicating over both IPv4 and IPv6.

# 7.2 Name Changes

Most of the changes required are straightforward and mechanical, though some may require a bit of code restructuring. For example, a routine that returns an int data type holding an IPv4 address may need to be modified to take as an extra parameter a pointer to an `in6_addr` into which it writes the IPv6 address. Table 7-1 summarizes the changes you must make to your application's code.

Table 7-1 Name Changes
Search file for | Replace with | Comments
--- | --- | ---
AF_INET | AF_INET6 | Replace with IPv6 address family macro.
PF_INET | PF_INET6 | Replace with IPv6 protocol family macro.
INADDR_ANY | in6addr_any | Replace with IPv6 global variable.

# 7.3 Structure Changes

The structure names and field names have changed for the following structures:

- `in_addr`
- `sockaddr_in`
- `sockaddr`
- `hostent`

The following sections discuss these changes.

## 7.3.1 in_addr Structure

Applications that use the IPv4 `in_addr` structure must be changed to use the IPv6 `in6_addr` structure, as follows:

IPv4 Structure | IPv6 Structure
--- | ---
`struct in_addr` `unsigned int s_addr` | `struct in6_addr` `uint8_t s6_addr`

Make the following changes to your application, as needed:

1. Change the structure name `in_addr` to `in6_addr` .
2. Change the data type from `unsigned int` to `uint8_t` and the field name `s_addr` to `s6_addr` .

## 7.3.2 sockaddr Structure

Applications that use the generic socket address structure (sockaddr) to hold an AF_INET socket address ( `sockaddr_in` ) must be changed to use the AF_INET6 `sockaddr_in6` structure, as follows:

AF_INET Structure | AF_INET6 Structure
--- | ---
`struct sockaddr` | `struct sockaddr_in6`

Make the following change to your application, as needed:

1. Change structure name `sockaddr` to `sockaddr_in6` .
   For example, `sizeof(struct sockaddr)` .

   Note A `sockaddr_in6` structure is larger than a `sockaddr` structure.

## 7.3.3 sockaddr_in Structure

Applications that use the BSD Version 4.4 IPv4 `sockaddr_in` structure must be changed to use the IPv6 `sockaddr_in6` structure, as follows:

IPv4 Structure | IPv6 Structure
--- | ---
`struct sockaddr_in` `unsigned char sin_len` `sa_family_t sin_family` `in_port_t sin_port` `struct addr sin_addr` | `struct sockaddr_in6` `uint8_t sin6_len` `sa_family_t sin6_family` `int_port_t sin6_port` `struct in6_addr sin6_addr`

Make the following changes to your application, as needed:

1. Change structure name `sockaddr_in` to `sockaddr_in6` . Initialize the entire `sockaddr_in6` structure to zero after your structure declarations.
2. Change the data type `unsigned char` to `uint8_t` and the field name `sin_len` to `sin6_len` .
3. Change the field name `sin_family` to `sin6_family` .
4. Change the field name `sin_port` to `sin6_port` .
5. Change the field name `sin_addr` to `sin6_addr` .

## 7.3.4 hostent Structure

Applications that use the `hostent` structure must be changed to use the `addrinfo` structure, as follows:

AF_INET Structure | AF_INET6 Structure
--- | ---
`struct hostent` | `struct addrinfo`

Make the following change to your application, as needed:

1. Change the structure name `hostent` to `addrinfo` .

# 7.4 Function Call Changes

The names and parameters have changed for the following function calls:

- `gethostbyaddr`
- `gethostbyname`
- `inet_ntoa`
- `inet_addr`

The following sections discuss these changes.

## 7.4.1 gethostbyaddr Function Call

Applications that use the IPv4 `gethostbyaddr` function call must be changed to use the IPv6 `getnameinfo` function call, as follows:

AF_INET Call | AF_INET6 Call
--- | ---
gethostbyaddr( xxx,4,AF_INET) | err=getnameinfo( &sockaddr, sockaddr_len, node_name, name_len, service, service_len, flags);

Make the following change to your application, as needed:

1. Change the function name from `gethostbyaddr` to `getnameinfo` and provide a pointer to the socket address structure, a character string for the returned node name, an integer for the length of the returned node name, a character string to receive the returned service name, an integer for the length of the returned service name, and an integer that specifies the type of address processing to be performed.

## 7.4.2 gethostbyname Function Call

Applications that use the `gethostbyname` function call must be changed to use the `getaddrinfo` function call, as folllows:

AF_INET Call | AF_INET6 Call
--- | ---
gethostbyname( name) | err=getaddrinfo( node_name, service_name, &hints, &result); . . . freeaddrinfo( &result);

Make the following changes to your application, as needed:

1. Change the function name from `gethostbyname` to `getaddrinfo` and provide a character string that contains the node name, a character string that contains the service name to use, a pointer to a `hints` structure that contains processing options, and a pointer to an `addrinfo` structure or structures for the returned address information.
2. Add a call to the `freeaddrinfo` routine to free the `addrinfo` structure or structures when your application is finished using them.

## 7.4.3 inet_ntoa Function Call

Applications that use the `inet_ntoa` function call must be changed to use the `getnameinfo` function call, as follows:

AF_INET Call | AF_INET6 Call
--- | ---
inet_ntoa( addr) | err=getnameinfo( &sockaddr, sockaddr_len, node_name, name_len, service, service_len, NI_NUMERICHOST);

Make the following change to your application, as needed:

1. Change the function name from `inet_ntoa` to `getnameinfo` and provide a pointer to the socket address structure, a character string for the returned node name, an integer for the length of the returned node name, a character string to receive the returned service name, an integer for the length of the returned service name, and the NI_NUMERICHOST flag.

## 7.4.4 inet_addr Function Call

Applications that use the `inet_addr` function call must be changed to use the `getaddrinfo` function call, as follows:

AF_INET Call | AF_INET6 Call
--- | ---
result=inet_addr( &string) | err=getaddrinfo( node_name, service_name, &hints, &result); . . . freeaddrinfo( &result);

Make the following change to your application, as needed:

1. Change the function name from `inet_addr` to `getaddrinfo` and provide a character string that contains the node name, a character string that contains the service name to use, a pointer to a hints structure that contains the AI_NUMERICHOST option, and a pointer to an `addrinfo` structure or structures for the returned address information.
2. Add a call to the `freeaddrinfo` routine to free the `addrinfo` structure or structures when your application is finished using them.

# 7.5 Other Application Changes

In addition to the name changes, you should review your code for specific uses of IP address information and variables.

## 7.5.1 Comparing IP Addresses

If your application compares IP addresses or tests IP addresses for equality, the `in6_addr` structure changes (see in Section 7.3.1) will change the comparison of int quantities to a comparison of structures. This will break the code and cause compiler errors.

Make either of the following changes to your application, as needed:

AF_INET Code | AF_INET6 Code
--- | ---
(addr1->s_addr == addr2->s_addr) | (memcmp(addr1, addr2, sizeof(struct in6_addr)) == 0)

1. Change the equality expression to one that uses the `memcmp` (memory comparison) function.

AF_INET Code | AF_INET6 Code
--- | ---
(addr1->s_addr == addr2->s_addr) | IN6_ARE_ADDR_EQUAL(addr1, addr2)

1. Change the equality expression to one that uses the `IN6_ARE_ADDR_EQUAL` macro.

Previous | Next | Contents