Merge pull request #1184 from G10h4ck/linkLocalFallback

[0.6.4] Use link local address only if necessary fix #292
This commit is contained in:
csoler 2018-02-23 14:00:39 +01:00 committed by GitHub
commit ff7633fefe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 183 additions and 69 deletions

View File

@ -3,7 +3,8 @@
*
* 3P/PQI network interface for RetroShare.
*
* Copyright 2007-2011 by Robert Fernie.
* Copyright (C) 2007-2011 Robert Fernie
* Copyright (C) 2015-2018 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -24,6 +25,7 @@
*/
#include <time.h>
#include <vector>
#include "pqi/p3netmgr.h"
@ -37,8 +39,7 @@
#include "util/extaddrfinder.h"
#include "util/dnsresolver.h"
//#include "util/rsprint.h"
//#include "util/rsdebug.h"
struct RsLog::logInfo p3netmgrzoneInfo = {RsLog::Default, "p3netmgr"};
#define p3netmgrzone &p3netmgrzoneInfo
@ -165,11 +166,6 @@ void p3NetMgrIMPL::setManagers(p3PeerMgr *peerMgr, p3LinkMgr *linkMgr)
mLinkMgr = linkMgr;
}
//void p3NetMgrIMPL::setDhtMgr(p3DhtMgr *dhtMgr)
//{
// mDhtMgr = dhtMgr;
//}
#ifdef RS_USE_DHT_STUNNER
void p3NetMgrIMPL::setAddrAssist(pqiAddrAssist *dhtStun, pqiAddrAssist *proxyStun)
{
@ -1020,19 +1016,41 @@ bool p3NetMgrIMPL::checkNetAddress()
}
else
{
// TODO: Sat Oct 24 15:51:24 CEST 2015 The fact of having just one local address is a flawed assumption, this should be redesigned soon.
std::list<sockaddr_storage> addrs;
std::list<sockaddr_storage>::iterator it;
/* TODO: Sat Oct 24 15:51:24 CEST 2015 The fact of having just one local
* address is a flawed assumption, this should be redesigned as soon as
* possible. It will require complete reenginering of the network layer
* code. */
std::vector<sockaddr_storage> addrs;
if (getLocalAddresses(addrs))
for(it = addrs.begin(); (it != addrs.end() && !validAddr); ++it)
if(sockaddr_storage_isValidNet(*it) && !sockaddr_storage_isLoopbackNet(*it))
{
for (auto it = addrs.begin(); it!=addrs.end(); ++it)
{
sockaddr_storage& addr(*it);
if( sockaddr_storage_isValidNet(addr) &&
!sockaddr_storage_isLoopbackNet(addr) &&
!sockaddr_storage_isLinkLocalNet(addr))
{
prefAddr = *it;
prefAddr = addr;
validAddr = true;
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET)
std::cout << "p3NetMgrIMPL::checkNetAddress() prefAddr: " << sockaddr_storage_iptostring(prefAddr) << std::endl;
#endif
break;
}
}
/* If no satisfactory local address has been found yet relax and
* accept also link local addresses */
if(!validAddr) for (auto it = addrs.begin(); it!=addrs.end(); ++it)
{
sockaddr_storage& addr(*it);
if( sockaddr_storage_isValidNet(addr) &&
!sockaddr_storage_isLoopbackNet(addr) )
{
prefAddr = addr;
validAddr = true;
break;
}
}
}
}

View File

@ -29,7 +29,7 @@
#include "util/rsnet.h"
#include "serialiser/rstlvaddrs.h"
#define MAX_ADDRESS_LIST_SIZE 4
#define MAX_ADDRESS_LIST_SIZE 10
class pqiIpAddress
{

View File

@ -3,7 +3,8 @@
*
* 3P/PQI network interface for RetroShare.
*
* Copyright 2004-2006 by Robert Fernie.
* Copyright (C) 2004-2006 Robert Fernie.
* Copyright (C) 2015-2018 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -284,7 +285,7 @@ int inet_aton(const char *name, struct in_addr *addr)
# include <net/if.h>
#endif // WINDOWS_SYS
bool getLocalAddresses(std::list<sockaddr_storage> & addrs)
bool getLocalAddresses(std::vector<sockaddr_storage>& addrs)
{
addrs.clear();

View File

@ -3,7 +3,8 @@
*
* 3P/PQI network interface for RetroShare.
*
* Copyright 2004-2006 by Robert Fernie.
* Copyright (C) 2004-2006 Robert Fernie.
* Copyright (C) 2015-2018 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -24,10 +25,10 @@
*/
#ifndef MRK_PQI_NETWORKING_HEADER
#define MRK_PQI_NETWORKING_HEADER
#include <vector>
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
#ifndef WINDOWS_SYS
@ -95,7 +96,7 @@ void showSocketError(std::string &out);
std::string socket_errorType(int err);
bool getLocalAddresses(std::list<struct sockaddr_storage> & addrs);
bool getLocalAddresses(std::vector<sockaddr_storage> & addrs);
/* universal socket interface */

View File

@ -3,7 +3,8 @@
*
* Services for RetroShare.
*
* Copyright 2004-2013 by Robert Fernie.
* Copyright (C) 2004-2013 Robert Fernie.
* Copyright (C) 2018 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -25,11 +26,15 @@
#include "services/p3discovery2.h"
#include "pqi/p3peermgr.h"
#include "pqi/pqinetwork.h" // for getLocalAddresses
#include "util/rsversioninfo.h"
#include "retroshare/rsiface.h"
#include "rsserver/p3face.h"
#include <vector> // for std::vector
#include <algorithm> // for std::random_shuffle
// Interface pointer.
RsDisc *rsDisc = NULL;
@ -38,7 +43,9 @@ RsDisc *rsDisc = NULL;
* #define P3DISC_DEBUG 1
****/
static bool populateContactInfo(const peerState &detail, RsDiscContactItem *pkt,bool include_ip_information)
static bool populateContactInfo( const peerState &detail,
RsDiscContactItem *pkt,
bool include_ip_information )
{
pkt->clear();
@ -341,10 +348,56 @@ void p3discovery2::sendOwnContactInfo(const SSLID &sslid)
std::cerr << std::endl;
#endif
peerState detail;
if (mPeerMgr->getOwnNetStatus(detail))
if (mPeerMgr->getOwnNetStatus(detail))
{
/* Workaround to spread multiple local ip addresses when presents. This
* is needed because RS wrongly assumes that there is just one active
* local ip address at time. */
std::vector<sockaddr_storage> addrs;
if(!detail.hiddenNode && getLocalAddresses(addrs))
{
/* To work around MAX_ADDRESS_LIST_SIZE addresses limitation,
* let's shuffle the list of
* local addresses in the hope that with enough time every local
* address is advertised to trusted nodes so they may try to
* connect to all of them including the most convenient if a local
* connection exists.*/
std::random_shuffle(addrs.begin(), addrs.end());
for (auto it = addrs.begin(); it!=addrs.end(); ++it)
{
sockaddr_storage& addr(*it);
if( sockaddr_storage_isValidNet(addr) &&
!sockaddr_storage_isLoopbackNet(addr) &&
!sockaddr_storage_sameip(addr, detail.localaddr) )
{
pqiIpAddress pqiIp;
sockaddr_storage_clear(pqiIp.mAddr);
pqiIp.mAddr.ss_family = addr.ss_family;
sockaddr_storage_copyip(pqiIp.mAddr, addr);
sockaddr_storage_setport(
pqiIp.mAddr,
sockaddr_storage_port(detail.localaddr) );
pqiIp.mSeenTime = time(nullptr);
pqiIp.mSrc = 0;
detail.ipAddrs.updateLocalAddrs(pqiIp);
}
}
}
RsDiscContactItem *pkt = new RsDiscContactItem();
populateContactInfo(detail, pkt, !rsPeers->isHiddenNode(sslid)); // we dont send our own IP to an hidden node. It will not use it anyway.
/* Cyril: we dont send our own IP to an hidden node. It will not use it
* anyway. */
populateContactInfo(detail, pkt, !rsPeers->isHiddenNode(sslid));
/* G10h4ck: sending IP information also to hidden nodes has proven very
* helpful in the usecase of non hidden nodes, that share a common
* hidden trusted node, to discover each other IP.
* Advanced/corner case non hidden node users that want to hide their
* IP to a specific hidden ~trusted~ node can do it through the
* permission matrix. Disabling this instead will make life more
* difficult for average user, that moreover whould have no way to
* revert an hardcoded policy. */
//populateContactInfo(detail, pkt, true);
pkt->version = RsUtil::retroshareVersion();
pkt->PeerId(sslid);
@ -433,10 +486,11 @@ void p3discovery2::recvOwnContactInfo(const SSLID &fromId, const RsDiscContactIt
void p3discovery2::updatePeerAddresses(const RsDiscContactItem *item)
{
if (item->isHidden)
mPeerMgr->setHiddenDomainPort(item->sslId, item->hiddenAddr, item->hiddenPort);
mPeerMgr->setHiddenDomainPort(item->sslId, item->hiddenAddr,
item->hiddenPort);
else
{
mPeerMgr->setDynDNS(item->sslId, item->dyndns);
mPeerMgr->setDynDNS(item->sslId, item->dyndns);
updatePeerAddressList(item);
}
}
@ -447,8 +501,19 @@ void p3discovery2::updatePeerAddressList(const RsDiscContactItem *item)
if (item->isHidden)
{
}
else if(!mPeerMgr->isHiddenNode(rsPeers->getOwnId())) // we don't store IP addresses if we're a hidden node. Normally they should not be sent to us, except for old peers.
else if(!mPeerMgr->isHiddenNode(rsPeers->getOwnId()))
{
/* Cyril: we don't store IP addresses if we're a hidden node.
* Normally they should not be sent to us, except for old peers. */
/* G10h4ck: sending IP information also to hidden nodes has proven very
* helpful in the usecase of non hidden nodes, that share a common
* hidden trusted node, to discover each other IP.
* Advanced/corner case non hidden node users that want to hide their
* IP to a specific hidden ~trusted~ node can do it through the
* permission matrix. Disabling this instead will make life more
* difficult for average user, that moreover whould have no way to
* revert an hardcoded policy. */
pqiIpAddrSet addrsFromPeer;
addrsFromPeer.mLocal.extractFromTlv(item->localAddrList);
addrsFromPeer.mExt.extractFromTlv(item->extAddrList);
@ -471,13 +536,12 @@ void p3discovery2::updatePeerAddressList(const RsDiscContactItem *item)
void p3discovery2::sendPGPList(const SSLID &toId)
{
updatePgpFriendList();
RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/
RS_STACK_MUTEX(mDiscMtx);
#ifdef P3DISC_DEBUG
std::cerr << "p3discovery2::sendPGPList() to " << toId;
std::cerr << std::endl;
std::cerr << "p3discovery2::sendPGPList() to " << toId << std::endl;
#endif
RsDiscPgpListItem *pkt = new RsDiscPgpListItem();
@ -508,7 +572,7 @@ void p3discovery2::updatePgpFriendList()
std::cerr << std::endl;
#endif
RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/
RS_STACK_MUTEX(mDiscMtx);
#define PGP_MAX_UPDATE_PERIOD 300
@ -863,26 +927,20 @@ void p3discovery2::sendContactInfo_locked(const PGPID &aboutId, const SSLID &toI
void p3discovery2::processContactInfo(const SSLID &fromId, const RsDiscContactItem *item)
{
RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/
(void) fromId; // remove unused parameter warnings, debug only
RS_STACK_MUTEX(mDiscMtx);
if (item->sslId == rsPeers->getOwnId())
{
if(sockaddr_storage_isExternalNet(item->currentConnectAddress.addr))
mPeerMgr->addCandidateForOwnExternalAddress(item->PeerId(), item->currentConnectAddress.addr) ;
#ifdef P3DISC_DEBUG
std::cerr << "p3discovery2::processContactInfo(" << fromId << ") PGPID: ";
std::cerr << item->pgpId << " Ignoring Info on self";
std::cerr << std::endl;
#else
/* remove unused parameter warnings */
(void) fromId;
#endif
delete item;
{
if(sockaddr_storage_isExternalNet(item->currentConnectAddress.addr))
mPeerMgr->addCandidateForOwnExternalAddress(
item->PeerId(), item->currentConnectAddress.addr);
delete item;
return;
}
/* */
std::map<PGPID, DiscPgpInfo>::iterator it;
it = mFriendList.find(item->pgpId);
if (it == mFriendList.end())
@ -895,7 +953,8 @@ void p3discovery2::processContactInfo(const SSLID &fromId, const RsDiscContactIt
std::cerr << std::endl;
#endif
/* THESE ARE OUR FRIEND OF FRIENDS ... pass this information along to NetMgr & DHT...
/* THESE ARE OUR FRIEND OF FRIENDS ... pass this information along to
* NetMgr & DHT...
* as we can track FOF and use them as potential Proxies / Relays
*/
@ -941,7 +1000,10 @@ void p3discovery2::processContactInfo(const SSLID &fromId, const RsDiscContactIt
// set last seen to RS_PEER_OFFLINE_NO_DISC minus 1 so that it won't be shared with other friends
// until a first connection is established
mPeerMgr->addFriend(item->sslId, item->pgpId, item->netMode, RS_VS_DISC_OFF, RS_VS_DHT_FULL, time(NULL) - RS_PEER_OFFLINE_NO_DISC - 1, RS_NODE_PERM_ALL);
mPeerMgr->addFriend( item->sslId, item->pgpId, item->netMode,
RS_VS_DISC_OFF, RS_VS_DHT_FULL,
time(NULL) - RS_PEER_OFFLINE_NO_DISC - 1,
RS_NODE_PERM_ALL );
updatePeerAddresses(item);
}
}

View File

@ -4,6 +4,7 @@
* Universal Networking Header for RetroShare.
*
* Copyright 2007-2008 by Robert Fernie.
* Copyright (C) 2015-2018 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -147,25 +148,25 @@ bool isLoopbackNet(const struct in_addr *addr)
return (taddr == (127 << 24 | 1));
}
bool isPrivateNet(const struct in_addr *addr)
bool isPrivateNet(const struct in_addr *addr)
{
in_addr_t taddr = ntohl(addr->s_addr);
// 10.0.0.0/8
// 172.16.0.0/12
// 192.168.0.0/16
// 169.254.0.0/16
if ((taddr>>24 == 10) ||
(taddr>>20 == (172<<4 | 16>>4)) ||
(taddr>>16 == (192<<8 | 168)) ||
(taddr>>16 == (169<<8 | 254)))
{
if ( (taddr>>24 == 10) || // 10.0.0.0/8
(taddr>>20 == (172<<4 | 16>>4)) || // 172.16.0.0/12
(taddr>>16 == (192<<8 | 168)) || // 192.168.0.0/16
(taddr>>16 == (169<<8 | 254)) ) // 169.254.0.0/16
return true;
}
else
{
return false;
}
return false;
}
bool isLinkLocalNet(const struct in_addr *addr)
{
in_addr_t taddr = ntohl(addr->s_addr);
if ( taddr>>16 == (169<<8 | 254) ) return true; // 169.254.0.0/16
return false;
}
bool isExternalNet(const struct in_addr *addr)

View File

@ -4,6 +4,7 @@
* Universal Networking Header for RetroShare.
*
* Copyright 2004-2006 by Robert Fernie.
* Copyright (C) 2015-2018 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -72,6 +73,7 @@ void sockaddr_clear(struct sockaddr_in *addr);
bool isValidNet(const struct in_addr *addr);
bool isLoopbackNet(const struct in_addr *addr);
bool isPrivateNet(const struct in_addr *addr);
bool isLinkLocalNet(const struct in_addr *addr);
bool isExternalNet(const struct in_addr *addr);
// uses a re-entrant version of gethostbyname
@ -128,6 +130,7 @@ bool sockaddr_storage_isnull(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);
bool sockaddr_storage_isLinkLocalNet(const struct sockaddr_storage &addr);
bool sockaddr_storage_isExternalNet(const struct sockaddr_storage &addr);
bool rs_inet_ntop(const sockaddr_storage &addr, std::string &dst);

View File

@ -4,6 +4,7 @@
* sockaddr_storage functions for RetroShare.
*
* Copyright 2013-2013 by Robert Fernie.
* Copyright (C) 2015-2018 Gioacchino Mazzurco <gio@eigenlab.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -389,7 +390,8 @@ void sockaddr_storage_dump(const sockaddr_storage & addr, std::string * outputSt
std::stringstream output;
output << "sockaddr_storage_dump(addr) ";
switch (addr.ss_family){
switch (addr.ss_family)
{
case AF_INET:
{
const sockaddr_in * in = (const sockaddr_in *) & addr;
@ -421,7 +423,8 @@ void sockaddr_storage_dump(const sockaddr_storage & addr, std::string * outputSt
for( uint32_t i = 0; i < sizeof(addr); ++i )
output << std::setw(2) << std::setfill('0') << std::hex << +buf[i];
// The unary +buf[i] operation forces a no-op type conversion to an int with the correct sign
}}
}
}
if(outputString)
{
@ -578,6 +581,31 @@ bool sockaddr_storage_isPrivateNet(const struct sockaddr_storage &addr)
return false;
}
bool sockaddr_storage_isLinkLocalNet(const struct sockaddr_storage &addr)
{
#ifdef SS_DEBUG
std::cerr << __PRETTY_FUNCTION__ << std::endl;
#endif
switch(addr.ss_family)
{
case AF_INET:
return isLinkLocalNet(&(to_const_ipv4_ptr(addr)->sin_addr));
case AF_INET6:
std::cerr << __PRETTY_FUNCTION__ << " for AF_INET6 not implemented"
<< std::endl;
break;
default:
#ifdef SS_DEBUG
std::cerr << __PRETTY_FUNCTION__ <<" INVALID Family:" << std::endl;
sockaddr_storage_dump(addr);
#endif
break;
}
return false;
}
bool sockaddr_storage_isExternalNet(const struct sockaddr_storage &addr)
{