tags:

views:

619

answers:

5

I need to add IPv6 support to an existing socket-based application which currently only supports IPv4. To embrace the incoming era of IPv6, someone ordered me to add an IPv6 interface for the app and let the outside world to choose either the IPv4 interface or the IPv6 interface when trying to communicate with the app.

My question is: is it true that for the socket handling API level in Linux, there is no difference between handling an IPv4 based socket and IPv6 based socket?

Further more, is it possible to let a socket listen on two IP addresses with same port? If that is true, then to implement the requirement is a trivial work, I guess.

A: 

I believe there is a difference, mainly how IP addresses are assigned/displayed and subnet masks.

Methods which take the incoming IPv4 address, will not work and throw an exception if a pure IPv6 is given to them, therefore your methods will need to check what kind of connection was initiated, other than that i don't think so.

LnDCobra
A: 

IPv6 is 128bit address space and offers more features(stateless, multicast, simpler processing for routers, to name but a few) in comparison to IPv4 (which is 32bit), the address space for IPv4 is running out, but with the help of NAT/SNAT it may increase longevity of the IPv4 Protocol. Using IPv6 is dependant on whether the OS can support the new protocol. It is certainly available on Windows 7, Linux...The main thing is that IPv6 is backwards compatible with IPv4...

To answer your question, that depends on the API level provided the OS can support the IPv6 network stack, Here is an example of IPv6 sockets example as found on MSDN, for Linux, usage of sockets is mostly the same with the exception that you will be using sockaddr_in6...

Hope this helps, Best regards, Tom.

tommieb75
+1  A: 

Much of the socket handling is the same for both IPv4 and IPv6. On the server, once you have bound your address, the calls to listen, accept, recv and send will all work the same for both IPv4 and IPv6 connections.

But any functions that deal with addresses such as connect, bind, getsockname, getpeername will need to be modified as you need to use a sockaddr_in6. Also, you need to modify the functions that work with address (for example, calls to inet_addr need to be changed to inet_pton).

On Linux, if you bind to in6addr_any, both IPv4 and IPv6 connections to that port will work (although this will could listen to more then 2 addresses because it will also listen on the IPv4 loopback 127.0.0.1 and the IPv6 loopback ::1). But on Windows, I have never been able to get that to work and need to listen on one socket for IPv4 and a different socket for IPv6.

R Samuel Klatchko
In Windows, the ability for a single socket to listen and accept both IPv4 and IPv6 clients on a single port was introduced in Vista, via its re-designed dual-stack socket stack architecture. Create an IPv6 listening socket and set the new IPV6_V6ONLY socket option to False to allow IPv4 clients on it.
Remy Lebeau - TeamB
@RemyLeabeauTeamB - thank you - that information is very helpful.
R Samuel Klatchko
+1  A: 

It is not possible to listen on 2 different IP addresses with 1 TCP socket, however if you listen on all interfaces using the in6addr_any address, that will include all IPv4 addresses as well (though I believe e.g. linux has a kernel option to disable that mapping).

The (newer version of) socket API is quite transparent as to whether you're using IPv4 or IPv6, but quite great care must be taken over how an IPv4 application is typically coded.

e.g. this IPv4 code which accepts a connection and prints out the address of the remote host:

 struct sockaddr_in client_addr;
 socklen_t addr_len = sizeof(client_addr);
 client_data->fd = accept(server_fd,(struct sockaddr*)&client_addr,&addr_len);
 log_printf("New client from %s\n",inet_ntoa(client_addr.sin_addr.s_addr));

Would have to be converted to the following, which handles both IPv4 and IPv6

 struct sockaddr_storage client_addr;
 char numeric_addr[INET6_ADDRSTRLEN];
 socklen_t addr_len = sizeof(client_addr);
 client_data->fd = accept(server_fd,(struct sockaddr*)&client_addr,&addr_len);
 if(client_addr.ss_family == AF_INET)
    log_printf("New client from %s\n",inet_ntop(client_addr.ss_family,((struct sockaddr_in*)&client_addr)->sin_addr.s_addr ,numeric_addr,sizeof numeric_addr));
 else if(client_addr.ss_family == AF_INET6)
    log_printf("New client from %s\n",inet_ntop(client_addr.ss_family,((struct sockaddr_in6*)&client_addr)->sin6_addr ,numeric_addr,sizeof numeric_addr));

Though I believe you could do it even more elegantly and transparent with getaddrinfo()

Here's additional notes on IP layer independance: http://uw714doc.sco.com/en/SDK_netapi/sockC.PortIPv4appIPv6.html http://www.kame.net/newsletter/19980604/

nos
@nos : thanks for you help. I have one more question, is it possible to bind a udp socket to more than one ip address ? for example, one for ipv4 and one for ipv6 totally 2 .
Haiyuan Zhang
No, you can't bind an UDP socket to more than 1 (or all) ip addresses either. You can with SCTP though, utilizing its multi-homing features. Fot TCP or UDP you'd have to create 1 socket for each address you want to listen on, unless you want to listen on all ip addresses
nos
+1  A: 

Beej's Guide to Network Programming addresses the differences in coding for IPv4 and IPv6. http://beej.us/guide/bgnet/

He has dedicated one section to changing your existing IPv4 code to handle IPv6.

He also explains how to code abstractly at the socket level so that you do not need to know whether or not you are dealing with an IPv4 address, or an IPv6.

SuperShabam