|
|
One of the main objectives when implementing IPv6 in UnixWare 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.
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:
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.
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) { ...
The address and protocol family constants for IPv6 are:
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;
Three IPv4 functions have been succeeded by new functions:
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 macros and functions are provided for address/host name handling:
getaddrinfo(3N) and getnameinfo(3N) can be used for IPv4 and IPv6 applications. There are similar functions already defined; gethostbyname(3N) and gethostbyname2(3N) are similar to getaddrinfo(3N), and gethostbyaddr(3N) is similar to getnameinfo(3N). 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(3N) and getnameinfo(3N) instead of their older counterparts in you applications. The resulting code will be clearer and more portable.