Reputation: 2002
What is the best way to implement socket interface to support IPV6. The existing code suppports IPV4 only. Now, to support IPV6 also I have few doubts...
1) Should _I replace all the APIs of IPV4 by IPV6 APIs. Say AF_INET by AF_INET6, sockaddr_in by sockaddr_in6 etc. Will these new APIs support both the protocols.
2) Or should I keep the condition this way...
#ifdef IPV6_SUPPORT
sockaddr_in6 addr;
RTMemoryUtil::memset( &addr, 0, (int)sizeof( addr ) );
addr.sin6_family = AF_INET6;
addr.sin6_port = (unsigned short)htons( port );
RTMemoryUtil::memcpy( &addr.sin6_addr, address, (int)sizeof( *address ) );
#else
sockaddr_in addr;
RTMemoryUtil::memset( &addr, 0, (int)sizeof( addr ) );
addr.sin_family = AF_INET;
addr.sin_port = (unsigned short)htons( port );
RTMemoryUtil::memcpy( &addr.sin_addr, address, (int)sizeof( *address ) );
#endif
Please suggest if there is any better way or what is the flaw in the second process.
Upvotes: 1
Views: 4881
Reputation: 745
The other answers are on target, but there's another essential thing to consider: A sockaddr structure is SMALLER THAN the IPv6-required sockaddr_in6 structure. I was porting code that had this:
struct sockaddr salocal;
struct sockaddr_in * s_in = (struct sockaddr_in *) &salocal;
Replacing the second line with:
struct sockaddr_in6 * s_in6 = (struct sockaddr_in6 *) &salocal;
leads to problems because, while sockaddr_in
fits in a sockaddr
, sockaddr_in6
does not! However, sockaddr_storage
IS big enough to handle both IPv4 and IPv6.
Instead switch to something like:
struct sockaddr_storage salocal;
struct sockaddr_in6 * s_in6 = (struct sockaddr_in6 *) &salocal;
and then, when calling methods like bind, cast to (struct sockaddr *)
.
Upvotes: 1
Reputation: 12866
Technically neither option (1) or (2), you should migrate to IP family agnostic APIs and use struct sockaddr
and struct sockaddr_storage
instead of IPv4 and IPv6 hardwired structures. Stevens' gives good examples of creating an agnostic API, here is a similar method I employed:
http://code.google.com/p/openpgm/source/browse/trunk/openpgm/pgm/sockaddr.c
Upvotes: 5
Reputation: 507
Depending on target platforms you can set socket options to enable a socket to handle both IPv4 and IPv6 if a suitable dual stack is implemented. It will remove much of the work in your behalf.
http://long.ccaba.upc.es/long/045Guidelines/eva/ipv6.html and http://msdn.microsoft.com/en-us/library/bb513665(v=vs.85).aspx may help get started.
For many uses it may not be much of a change from your existing IPv4 code.
Upvotes: 3
Reputation: 363567
Either use a modern network programming library such as Boost.Asio, or (if you want to do it the C/sockets way) the getaddrinfo
interface. The latter was designed some ten years ago, so it should be available just about everywhere (at least Windows, Linux, BSD, Mac OS X). It has the added charm that it can also support exotic network protocols, given appropriate OS/C library support, so you can claim to support Protocol-Independent Distributed Cloud Computing®.
Upvotes: 4