Kundan Kumar
Kundan Kumar

Reputation: 2002

Best Way to implement Socket Interface to support both IPV6 and IPV4

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

Answers (4)

Alan Carwile
Alan Carwile

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

Steve-o
Steve-o

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

Boofhead
Boofhead

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

Fred Foo
Fred Foo

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

Related Questions