DOC HOME SITE MAP MAN PAGES GNU INFO SEARCH PRINT BOOK
 
Programming with sockets

Porting IPv4 applications to IPv6

One of the main objectives when implementing IPv6 in Release 6.0.0 was to provide a migration path to IPv6 while still enabling IPv4 applications to work. This has had the effect of reducing the amount of effort required to ``port'' an existing IPv4 application to IPv6. The checklist below highlights the various aspects of porting such an application.

Data structures

IPv4 applications use the sockaddr_in and in_addr structures to pass network address information between certain networking related functions.

IPv6 uses a larger address space and therefore uses different data structures to replace sockaddr_in and in_addr:


in6_addr
is used to store the 128-bit network address

sockaddr_in6
is used to store the remaining details, previously stored by sockaddr_in, that is, length of the data structure, address family, flowinfo, port number and in6_addr data structure.
Replace any occurrence of sockaddr_in with the sockaddr_in6 structure.

Another feature that was implemented at the same time as IPv6 was the move to support variable length sockets. In this new version the sin6_family is only 8-bits long unlike the original sin_family which was 16-bits long. The remaining 8 bits have been defined as sin6_len, and contains the length of the data structure. When modifying the sockaddr_in structure members to their new sockaddr_in6 names, it is not strictly necessary to fill in this member before using the structure. For example, if your application contained the following code:

   struct sockaddr_in server;
   ...
   server.sin_family = AF_INET;
   server.sin_port = 0;
   ...
To port this code to IPv6, you could modify it to:
   struct sockaddr_in6 server;
   ...
   server.sin6_len = sizeof(server);
   server.sin6_family = AF_INET6;
   server.sin6_port = 0;
   ...
but the assignment of server.sin6_len is not necessary.

INADDR_ANY and INADDR_LOOPBACK

Any occurrence of INADDR_ANY or INADDR_LOOPBACK must be modified to use the newer global variables in6addr_any or in6addr_loopback for assignments. If you need to initialize an in6_addr structure, use either the IN6ADDR_ANY_INIT or IN6ADDR_LOOPBACK_INIT macros.

For example, if your application contained the following code:

   struct sockaddr_in server;
   ...
   server.sin_len = sizeof(server);
   server.sin_family = AF_INET;
   server.sin_addr.s_addr = INADDR_ANY;
   server.sin_port = 0;
   if (bind(sock, (struct sockaddr *) &server, sizeof(server)) <0) {
   ...
To port it to IPv6, modify it to:
   struct sockaddr_in6 server;
   ...
   server.sin6_len = sizeof(server);
   server.sin6_family = AF_INET6;
   server.sin6_addr = in6addr_any;
   server.sin6_port = 0;
   if (bind(sock, (struct sockaddr *) &server, sizeof(server)) <0) {
   ...

Address and protocol family constants

The address and protocol family constants for IPv6 are:


AF_INET6
IPv6 address family.

PF_INET6
IPv6 protocol family.
Replace all occurrences of AF_INET in your application with AF_INET6 and all occurrences of PF_INET with PF_INET6. For example, if you application had the following line of code:
   server.sin_family = AF_INET;
alter the member name to its correct sockaddr_in6 name and change AF_INET to AF_INET6, as shown below:
   server.sin6_family = AF_INET6;

Substituting old IPv4 functions with newer IPv6 versions

Three IPv4 functions have been succeeded by new functions:


gethostbyname(S) retrieves the network host entry referenced by a host name with an IPv4 address. Replace this function with gethostbyname2(S), which retrieves the network host entry referenced by a host name and its address family, which will be AF_INET6.

inet_addr(S) interprets a character string representing an address in Internet ``dot'' notation (IPv4) and returns a value suitable for use as an Internet address. Replace this function with inet_pton(S), which can perform the same operation for both IPv4 and IPv6 address notations.

inet_ntoa(S) interprets an IPv4 internet address and converts it to a character string. Replace this function with inet_ntop(S), which can perform the same operation for both IPv4 and IPv6 addresses.

You must use inet_pton and inet_ntop in your IPv6 application because the functions they replace (inet_addr and inet_ntoa) are not IPv6 aware.

New IPv6 functions

New macros and functions are provided for address/host name handling:

For example, the IN6_IS_ADDR_UNSPECIFIED and IN6_IS_ADDR_V4MAPPED macros can be used to determine whether an incoming IPv6 address is a true IPv6 address, or an IPv4-mapped address. These macros will become useful when the underlying networks start to use IPv6. At this point IPv6 applications will be able to start using extended options such as flow labels and priorities. By using these macros, your application can determine whether the connected application will be able to interpret the extended IPv6 options, or if it should use the standard IPv4 options.

getaddrinfo(S) and getnameinfo(S) can be used for IPv4 and IPv6 applications. There are similar functions already defined; gethostbyname(S) and gethostbyname2(S) are similar to getaddrinfo(S), and gethostbyaddr(S) is similar to getnameinfo(S). The difference between the new and the old functions is that the newer functions are protocol independent, and therefore can support IPv6.

Consider using getaddrinfo(S) and getnameinfo(S) instead of their older counterparts in you applications. The resulting code will be clearer and more portable.


NOTE: Examples of how to incorporate getaddrinfo(S) into existing code is shown in ``Porting IPv6 -- examples''.


© 2005 The SCO Group, Inc. All rights reserved.
SCO OpenServer Release 6.0.0 -- 02 June 2005