Tentative unified address class is as follows {code} -class IpAddr + +#ifndef CONDOR_IPADDRESS_H +#define CONDOR_IPADDRESS_H + +class ipaddr { sockaddr_in6 storage; + const unsigned char* get_addr() const { + // field name of in6_addr is different from platform to platform + return (const unsigned char*)&storage.sin6_addr; + } + unsigned char* get_addr() { // field name of in6_addr is different from platform to platform return (unsigned char*)&storage.sin6_addr; } unsigned int& get_addr_header() { return *(unsigned int*)get_addr(); } + const unsigned int& get_v4_addr() const { return *(const unsigned int*)(get_addr()+12); } unsigned int& get_v4_addr() { return *(unsigned int*)(get_addr()+12); } public: - IpAddr() + ipaddr() { memset(&storage, 0, sizeof(storage)); } - IpAddr(int ip, unsigned port = 0) : IpAddr() + ipaddr(int ip, unsigned port = 0) { + ipaddr(); storage.sin6_family = AF_INET; storage.sin6_port = htons(port); // IPv4-mapped region @@ -142,35 +153,49 @@ get_v4_addr() = (unsigned int)ip; } - IpAddr(in_addr ip, unsigned port = 0) : IpAddr(ip.S_un.S_addr, port) + ipaddr(in_addr ip, unsigned port = 0) { + ipaddr(ip.s_addr, port); } - IpAddr(sockaddr_in* sin) : IpAddr(sin->sin_addr, sin->sin_port) + ipaddr(sockaddr_in* sin) { + ipaddr(sin->sin_addr, sin->sin_port); } - IpAddr(sockaddr_in6* sin6) + ipaddr(sockaddr_in6* sin6) { storage = *sin6; } - sockaddr_in to_sin() + sockaddr_in to_sin() const { sockaddr_in ret; memset(&ret, 0, sizeof(ret)); - if (storage.sin_family != AF_INET) { + if (!is_ipv4()) { // error.. return ret; } ret.sin_family = AF_INET; ret.sin_port = storage.sin6_port; - ret.sin_addr.S_un.S_addr = get_v4_addr(); + ret.sin_addr.s_addr = get_v4_addr(); + } + + const sockaddr_in6& to_sin6() const + { + return storage; + } + + bool is_ipv4() const + { + return storage.sin6_family == AF_INET; } }; +#endif + {endcode} As you see here, sockaddr_in6 is super-set of sockaddr_in. So, this implementation considers IPv6 as basis and providing compatibility to IPv4 usage.