improved IPv6 handling (Patch 19a39b42c4bb6256363b1624520c200835a9b93e from G10H4ck)

git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.6-IPv6@8198 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
csoler 2015-05-01 13:14:25 +00:00
parent 09d601aac0
commit d40a9002fa
7 changed files with 124 additions and 87 deletions

View file

@ -219,29 +219,23 @@ int p3BitDht::addBadPeer(const struct sockaddr_storage &addr, uint32_t /*reason*
int p3BitDht::addKnownPeer(const RsPeerId &pid, const struct sockaddr_storage &addr, uint32_t flags)
{
struct sockaddr_in addrv4;
sockaddr_storage tmpAddr = addr;
if (addr.ss_family != AF_INET)
if (!sockaddr_storage_ipv6_to_ipv4(tmpAddr))
{
std::cerr << "p3BitDht::addKnownPeer() Warning! Non IPv4 Address - Cannot handle IPV6 Yet. addr.ss_family=" << addr.ss_family;
std::cerr << std::endl;
sockaddr_clear(&addrv4);
if (flags & NETASSIST_KNOWN_PEER_ONLINE)
{
std::cerr << "p3BitDht::addKnownPeer() Non IPv4 Address & ONLINE. Abort()ing.";
std::cerr << std::endl;
return 0; // TODO:IPV6
}
#ifdef DEBUG_BITDHT
std::cerr << "p3BitDht::addKnownPeer() Warning! Cannot add non IPv4 Address" << std::endl;
sockaddr_storage_dump(addr);
#endif
return 0; // TODO:IPV6
}
else
{
// convert.
struct sockaddr_in *ap = (struct sockaddr_in *) &addr;
struct sockaddr_in *ap = (struct sockaddr_in *) &tmpAddr;
sockaddr_clear(&addrv4);
addrv4.sin_family = ap->sin_family;
addrv4.sin_addr = ap->sin_addr;
addrv4.sin_port = ap->sin_port;

View file

@ -975,31 +975,34 @@ bool p3PeerMgrIMPL::UpdateOwnAddress(const struct sockaddr_storage &localAddr, c
std::cerr << ")" << std::endl;
#endif
std::list<struct sockaddr_storage> lAddrs;
getLocalAddresses(lAddrs); // Better to have this outside mutex
{
/****** STACK LOCK MUTEX *******/
RsStackMutex stack(mPeerMtx); (void)stack;
mOwnState.localaddr = localAddr;
RS_STACK_MUTEX(mPeerMtx);
// update ip address list
uint16_t port = 0;
if(!sockaddr_storage_isnull(localAddr))
{
lAddrs.push_front(localAddr);
port = sockaddr_storage_port(localAddr);
}
if (!lAddrs.empty())
mOwnState.localaddr = lAddrs.front();
std::list<struct sockaddr_storage>::iterator it;
std::list<struct sockaddr_storage> lAddrs;
getLocalAddresses(lAddrs);
lAddrs.push_front(localAddr);
for ( it = lAddrs.begin(); it != lAddrs.end(); ++it)
{
pqiIpAddress ipAddressTimed;
ipAddressTimed.mAddr = *it;
sockaddr_storage_setport(ipAddressTimed.mAddr, sockaddr_storage_port(localAddr));
sockaddr_storage_setport(ipAddressTimed.mAddr, port);
ipAddressTimed.mSeenTime = time(NULL);
ipAddressTimed.mSrc = 0 ;
ipAddressTimed.mSrc = 0;
mOwnState.ipAddrs.updateLocalAddrs(ipAddressTimed);
}
}
{
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
//update ip address list
pqiIpAddress ipAddressTimed;
@ -1015,7 +1018,7 @@ bool p3PeerMgrIMPL::UpdateOwnAddress(const struct sockaddr_storage &localAddr, c
* This should keep people happy, and allow for misconfiguration!
*/
if (mOwnState.netMode & RS_NET_MODE_TRY_EXT)
if (mOwnState.netMode & RS_NET_MODE_TRY_EXT)
{
/**** THIS CASE SHOULD NOT BE TRIGGERED ****/
std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress() Disabling Update of Server Port ";
@ -1025,10 +1028,10 @@ bool p3PeerMgrIMPL::UpdateOwnAddress(const struct sockaddr_storage &localAddr, c
std::cerr << sockaddr_storage_tostring(mOwnState.serveraddr);
std::cerr << std::endl;
}
else if (mOwnState.netMode & RS_NET_MODE_EXT)
else if (mOwnState.netMode & RS_NET_MODE_EXT)
{
sockaddr_storage_copyip(mOwnState.serveraddr,extAddr);
sockaddr_storage_copyip(mOwnState.serveraddr, extAddr);
std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress() Disabling Update of Server Port ";
std::cerr << " as MANUAL FORWARD Mode";
std::cerr << std::endl;
@ -1037,10 +1040,9 @@ bool p3PeerMgrIMPL::UpdateOwnAddress(const struct sockaddr_storage &localAddr, c
std::cerr << std::endl;
}
else
{
mOwnState.serveraddr = extAddr;
}
}
} // end RS_STACK_MUTEX(mPeerMtx);
IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/
mLinkMgr->setLocalAddress(localAddr);

View file

@ -371,21 +371,25 @@ in_addr_t inet_network(const char *inet_name)
bool getLocalAddresses(std::list<struct sockaddr_storage> & addrs)
{
struct ifaddrs *ifsaddrs, *ifa;
if(getifaddrs(&ifsaddrs) != 0) exit(1);
if(getifaddrs(&ifsaddrs) != 0)
{
freeifaddrs(ifsaddrs);
return false;
}
addrs.clear();
for ( ifa = ifsaddrs; ifa; ifa = ifa->ifa_next )
if ( (ifa->ifa_flags & IFF_UP) && !(ifa->ifa_flags & IFF_LOOPBACK) )
{
sockaddr_storage * tmp = new sockaddr_storage;
if (sockaddr_storage_copyip(* tmp, * (const struct sockaddr_storage *) ifa->ifa_addr))
addrs.push_back(*tmp);
else delete tmp;
const sockaddr_storage & ifaaddr = * (const struct sockaddr_storage *) ifa->ifa_addr;
if (sockaddr_storage_isLinkLocal(ifaaddr)) continue;
sockaddr_storage tmp;
if (sockaddr_storage_copyip(tmp, ifaaddr)) addrs.push_back(tmp);
}
freeifaddrs(ifsaddrs);
return (!addrs.empty());
freeifaddrs(ifsaddrs);
return !addrs.empty();
}

View file

@ -604,12 +604,12 @@ int pqissl::Delay_Connection()
}
rslog(RSL_WARNING, pqisslzone,
"pqissl::Initiate_Connection() Already Attempt in Progress!");
"pqissl::Delay_Connection() Already Attempt in Progress!");
return -1;
}
int pqissl::Initiate_Connection()
int pqissl::Initiate_Connection()
{
int err;
struct sockaddr_storage addr = remote_addr;
@ -750,6 +750,7 @@ int pqissl::Initiate_Connection()
{
std::string out;
rs_sprintf(out, "pqissl::Initiate_Connection() connect returns:%d -> errno: %d error: %s\n", err, errno, socket_errorType(errno).c_str());
sockaddr_storage_dump(addr, &out);
if (errno == EINPROGRESS)
{

View file

@ -894,7 +894,9 @@ bool p3Peers::setVisState(const RsPeerId &id, uint16_t vs_disc, uint16_t vs_dht)
bool p3Peers::getProxyServer(std::string &addr, uint16_t &port, uint32_t &status)
{
std::cerr << "p3Peers::getProxyServer()" << std::endl;
#ifdef P3PEERS_DEBUG
std::cerr << "p3Peers::getProxyServer()" << std::endl;
#endif
struct sockaddr_storage proxy_addr;
mPeerMgr->getProxyServerAddress(proxy_addr);

View file

@ -110,7 +110,7 @@ std::string sockaddr_storage_tostring(const struct sockaddr_storage &addr);
std::string sockaddr_storage_familytostring(const struct sockaddr_storage &addr);
std::string sockaddr_storage_iptostring(const struct sockaddr_storage &addr);
std::string sockaddr_storage_porttostring(const struct sockaddr_storage &addr);
void sockaddr_storage_dump(const sockaddr_storage & addr);
void sockaddr_storage_dump(const sockaddr_storage & addr, std::string * outputString = NULL);
// output
//void sockaddr_storage_output(const struct sockaddr_storage &addr, std::ostream &out);
@ -118,6 +118,8 @@ void sockaddr_storage_dump(const sockaddr_storage & addr);
// net checks.
bool sockaddr_storage_isnull(const struct sockaddr_storage &addr);
bool sockaddr_storage_isLinkLocal(const struct sockaddr_storage &addr);
bool sockaddr_storage_isIPv4Mapped(const struct sockaddr_storage &addr);
bool sockaddr_storage_isValidNet(const struct sockaddr_storage &addr);
bool sockaddr_storage_isLoopbackNet(const struct sockaddr_storage &addr);
bool sockaddr_storage_isPrivateNet(const struct sockaddr_storage &addr);

View file

@ -27,6 +27,7 @@
#include "util/rsnet.h"
#include "util/rsstring.h"
#include "util/stacktrace.h"
#include "pqi/pqinetwork.h"
/***************************** Internal Helper Fns ******************************/
@ -180,8 +181,7 @@ bool sockaddr_storage_copyip(struct sockaddr_storage &dst, const struct sockaddr
uint16_t sockaddr_storage_port(const struct sockaddr_storage &addr)
{
#ifdef SS_DEBUG
std::cerr << "sockaddr_storage_port()";
std::cerr << std::endl;
std::cerr << "sockaddr_storage_port()" << std::endl;
#endif
switch(addr.ss_family)
{
@ -192,8 +192,9 @@ uint16_t sockaddr_storage_port(const struct sockaddr_storage &addr)
return sockaddr_storage_ipv6_port(addr);
break;
default:
std::cerr << "sockaddr_storage_port() invalid addr.ss_family" << std::endl;
std::cerr << "sockaddr_storage_port() invalid addr.ss_family ";
sockaddr_storage_dump(addr);
//print_stacktrace();
break;
}
return 0;
@ -310,27 +311,20 @@ bool sockaddr_storage_ipv6_to_ipv4(sockaddr_storage &addr)
if ( addr.ss_family == AF_INET ) return true;
if ( addr.ss_family == AF_INET6 )
if(sockaddr_storage_isIPv4Mapped(addr))
{
sockaddr_in6 & addr_ipv6 = (sockaddr_in6 &) addr;
bool ipv4m = addr_ipv6.sin6_addr.s6_addr16[5] == (u_int16_t) 0xffff;
for ( int i = 0; ipv4m && i < 5 ; ++i )
ipv4m &= addr_ipv6.sin6_addr.s6_addr16[i] == (u_int16_t) 0x0000;
u_int32_t ip = addr_ipv6.sin6_addr.s6_addr32[3];
u_int16_t port = addr_ipv6.sin6_port;
if(ipv4m)
{
u_int32_t ip = addr_ipv6.sin6_addr.s6_addr32[3];
u_int16_t port = addr_ipv6.sin6_port;
sockaddr_in & addr_ipv4 = (sockaddr_in &) addr;
sockaddr_in & addr_ipv4 = (sockaddr_in &) addr;
sockaddr_storage_clear(addr);
addr_ipv4.sin_family = AF_INET;
addr_ipv4.sin_port = port;
addr_ipv4.sin_addr.s_addr = ip;
sockaddr_storage_clear(addr);
addr_ipv4.sin_family = AF_INET;
addr_ipv4.sin_port = port;
addr_ipv4.sin_addr.s_addr = ip;
return true;
}
return true;
}
return false;
@ -478,26 +472,54 @@ std::string sockaddr_storage_porttostring(const struct sockaddr_storage &addr)
bool sockaddr_storage_isnull(const struct sockaddr_storage &addr)
{
#ifdef SS_DEBUG
std::cerr << "sockaddr_storage_isnull()";
std::cerr << std::endl;
std::cerr << "sockaddr_storage_isnull()" << std::endl;
#endif
if (addr.ss_family == 0)
return true;
switch(addr.ss_family)
{
case AF_INET:
return sockaddr_storage_ipv4_isnull(addr);
break;
case AF_INET6:
return sockaddr_storage_ipv6_isnull(addr);
break;
default:
return true;
break;
}
return true;
}
bool sockaddr_storage_isLinkLocal(const struct sockaddr_storage &addr)
{
#ifdef SS_DEBUG
std::cerr << "sockaddr_storage_isLinkLocal()" << std::endl;
#endif
switch(addr.ss_family)
{
case AF_INET:
return false; // TODO:IPv4
case AF_INET6:
{
const sockaddr_in6 * addr6 = (const sockaddr_in6 *) &addr;
u_int16_t mask = 0xc0ff; // Mask end prefix inverted because of IPv6 is big endian
return ((addr6->sin6_addr.s6_addr16[0] & mask ) == 0x80fe);
}
default:
return false;
}
}
bool sockaddr_storage_isIPv4Mapped(const struct sockaddr_storage &addr)
{
if (addr.ss_family == AF_INET6)
{
sockaddr_in6 & addr_ipv6 = (sockaddr_in6 &) addr;
bool ipv4m = addr_ipv6.sin6_addr.s6_addr16[5] == (u_int16_t) 0xffff;
for ( int i = 0; ipv4m && i < 5 ; ++i )
ipv4m &= addr_ipv6.sin6_addr.s6_addr16[i] == (u_int16_t) 0x0000;
return ipv4m;
}
return false;
}
bool sockaddr_storage_isValidNet(const struct sockaddr_storage &addr)
@ -587,8 +609,7 @@ bool sockaddr_storage_isExternalNet(const struct sockaddr_storage &addr)
return sockaddr_storage_ipv6_isExternalNet(addr);
break;
default:
std::cerr << "sockaddr_storage_isExternalNet() INVALID Family - error";
std::cerr << std::endl;
std::cerr << "sockaddr_storage_isExternalNet() INVALID Family - error" << std::endl;
break;
}
return false;
@ -703,14 +724,14 @@ bool sockaddr_storage_ipv6_copyip(struct sockaddr_storage &dst, const struct soc
dst_ptr->sin6_family = AF_INET6;
memcpy(&(dst_ptr->sin6_addr), &(src_ptr->sin6_addr), sizeof(src_ptr->sin6_addr));
dst_ptr->sin6_scope_id = src_ptr->sin6_scope_id;
return true;
}
uint16_t sockaddr_storage_ipv6_port(const struct sockaddr_storage &addr)
{
#ifdef SS_DEBUG
std::cerr << "sockaddr_storage_ipv6_port()";
std::cerr << std::endl;
std::cerr << "sockaddr_storage_ipv6_port()" << std::endl;
#endif
const struct sockaddr_in6 *ipv6_ptr = to_const_ipv6_ptr(addr);
uint16_t port = ntohs(ipv6_ptr->sin6_port);
@ -719,8 +740,9 @@ uint16_t sockaddr_storage_ipv6_port(const struct sockaddr_storage &addr)
bool sockaddr_storage_ipv6_setport(struct sockaddr_storage &addr, uint16_t port)
{
std::cerr << "sockaddr_storage_ipv6_setport()";
std::cerr << std::endl;
#ifdef SS_DEBUG
std::cerr << "sockaddr_storage_ipv6_setport()" << std::endl;
#endif
struct sockaddr_in6 *ipv6_ptr = to_ipv6_ptr(addr);
ipv6_ptr->sin6_port = htons(port);
@ -866,7 +888,7 @@ std::string sockaddr_storage_iptostring(const struct sockaddr_storage & addr)
return output;
}
void sockaddr_storage_dump(const sockaddr_storage & addr)
void sockaddr_storage_dump(const sockaddr_storage & addr, std::string * outputString)
{
// This function must not rely on others sockaddr_storage_*
@ -892,6 +914,8 @@ void sockaddr_storage_dump(const sockaddr_storage & addr)
output << "addr.ss_family = AF_INET6";
output << " in6->sin6_addr = ";
output << addrStr;
output << " in6->sin6_scope_id = ";
output << in6->sin6_scope_id;
output << " in6->sin6_port = ";
output << in6->sin6_port;
break;
@ -906,7 +930,15 @@ void sockaddr_storage_dump(const sockaddr_storage & addr)
output << addr.__ss_padding;
}}
std::cerr << output.str() << std::endl;
if(outputString)
{
outputString->append(output.str() + "\n");
#ifdef SS_DEBUG
std::cerr << output.str() << std::endl;
#endif
}
else
std::cerr << output.str() << std::endl;
}
/********************************* Net Checks ***********************************/
@ -1013,9 +1045,9 @@ bool sockaddr_storage_ipv6_isValidNet(const struct sockaddr_storage & )
bool sockaddr_storage_ipv6_isLoopbackNet(const struct sockaddr_storage & addr )
{
sockaddr_in6 & addr6 = (sockaddr_in6 &) addr;
bool isLp = (addr6.sin6_addr.s6_addr32[3] == 0x1);
bool isLp = (addr6.sin6_addr.s6_addr32[3] == 0x10000000); // IPv6 is big endian
for (int i=0; isLp && i<3; ++i)
isLp &= (addr6.sin6_addr.s6_addr32[i] == 0x0);
isLp &= (addr6.sin6_addr.s6_addr32[i] == 0x00000000);
#ifdef SS_DEBUG
sockaddr_storage_dump(addr);
@ -1034,13 +1066,13 @@ bool sockaddr_storage_ipv6_isPrivateNet(const struct sockaddr_storage &)
return false;
}
bool sockaddr_storage_ipv6_isExternalNet(const struct sockaddr_storage &)
bool sockaddr_storage_ipv6_isExternalNet(const struct sockaddr_storage & addr)
{
#ifdef SS_DEBUG
std::cerr << "sockaddr_storage_ipv6_isExternalNet() TODO" << std::endl;
#endif
return true;
return !sockaddr_storage_isLinkLocal(addr);
}