Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting C++ TCP/IP applications from IPv4 to IPv6. Difficult? Worth the trouble?

Tags:

Over the years I've developed a small mass of C++ server/client applications for Windows using WinSock (Routers, Web/Mail/FTP Servers, etc... etc...).

I’m starting to think more and more of creating an IPv6 version of these applications (While maintaining the original IPv4 version as well, of course).

Questions:

  1. What pitfalls might I run into?
  2. Is the porting/conversion difficult?
  3. Is the conversion worth it?


For a reference (or for fun), you can sneek a peak of the IPv4 code at the core of my applications.

like image 929
NTDLS Avatar asked Feb 26 '10 03:02

NTDLS


People also ask

Why is the switch from IPv4 to IPv6 so difficult?

Every device will need an IP address and there are far too few available addresses within the IPv4 system to handle the sheer quantity of connections. It's a problem that's been predicted and solved for many years, in theory at least. But IPv6 is being adopted at a glacially slow pace.

What are some of the challenges in transitioning from IPv4 to IPv6?

Difficulty in detecting and managing unknown or unauthorized IPv6 assets on existing IPv4 production networks. The added complexity of operating parallel IPv4 and IPv6 networks. A lack of IPv6 maturity in security products. The proliferation of IPv6 and IPv4 tunnels can complicate defenses.

Why are we converting from IPv4 to IPv6?

IPv6 helps make routing more efficient and hierarchical by reducing the routing table size. With the help of ISPs, IPv6 assembles the prefixes of various customer networks and introduces them to IPv6 internet as one common prefix. This makes the process faster and productive.

What problems might occur with IPv6?

The primary problem with transitioning to IPv6 is that it's not backward compatible with IPv4. Simply put, when IPv6 was first devised, it was not created to function with IPv4. So, if you decide to use an IPv6 address within a network that is strictly based on IPv4, all types of routing and DNS problems can occur.


1 Answers

getaddrinfo and getnameinfo are your friends.. As much as possible I suggest they be your best friends in your quest to provide IPv4 and IPv6 support in an existing application.

If done right by adding IPv6 support you also end up abstracting the system to the point where an unknown future IP protocol can run without code modification.

Normally when connecting you would fill out a socket structure, port, address family, IP address, converting address/ports to network byte order, etc.

With getaddrinfo you send an IP address or hostname and port or port name, and it returns a linked list with the structures and everything ready to be passed directly into socket() and connect().

getaddrinfo is critical for working with both IP protocols as it knows if the host has IPv6 or IPv4 connectivity and it knows if the peer does as well by looking at DNS AAAA vs A records and dynamically figures out which protocol(s) are available to service the specific connection request.

I highly advise against use of inet_pton(), inet_addr() or smiliar devices that are IP version specific. On the Windows platform specifically inet_pton() is not compatible with earlier versions of MS Windows (XP, 2003 et al.) unless you roll your own. Also advise against separate versions for IPv4 and IPv6... This is unworkable as a technical solution because in the near future both protocols will need to be used concurrently and people may not know ahead of time which to use. The socket interfaces are abstract and it's easy to detect dualstack or IPv6 support by attempting to create an IPv6 socket or attempt to set the IPv6 dualstack socket option for listeners. There is no reason the resulting application won't run on a system that does not support or know about IPv6.

For outgoing connections use PF_UNSPEC in getaddrinfo so that the address family is chosen for you when making outgoing connections. This, IMHO, is better than the dualstack approach because it allows platforms that do not support dualstack to work.

For incoming connections you can either bind IPv4/IPv6 sockets separately if it's reasonable given the design or use dualstack if you can't do separate listeners. When using dualstack getnameinfo returns an IPv6 address for IPv4 addresses which IMHO ends up being quite useless. A small utility routine can convert the string to a normal IPv4 address.

From my experience when done right you've removed dependencies on specific IP versions and ended up with less socket management code than you started.

like image 163
Einstein Avatar answered Sep 22 '22 02:09

Einstein