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. * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@ -24,6 +25,7 @@
*/ */
#include <time.h> #include <time.h>
#include <vector>
#include "pqi/p3netmgr.h" #include "pqi/p3netmgr.h"
@ -37,8 +39,7 @@
#include "util/extaddrfinder.h" #include "util/extaddrfinder.h"
#include "util/dnsresolver.h" #include "util/dnsresolver.h"
//#include "util/rsprint.h"
//#include "util/rsdebug.h"
struct RsLog::logInfo p3netmgrzoneInfo = {RsLog::Default, "p3netmgr"}; struct RsLog::logInfo p3netmgrzoneInfo = {RsLog::Default, "p3netmgr"};
#define p3netmgrzone &p3netmgrzoneInfo #define p3netmgrzone &p3netmgrzoneInfo
@ -165,11 +166,6 @@ void p3NetMgrIMPL::setManagers(p3PeerMgr *peerMgr, p3LinkMgr *linkMgr)
mLinkMgr = linkMgr; mLinkMgr = linkMgr;
} }
//void p3NetMgrIMPL::setDhtMgr(p3DhtMgr *dhtMgr)
//{
// mDhtMgr = dhtMgr;
//}
#ifdef RS_USE_DHT_STUNNER #ifdef RS_USE_DHT_STUNNER
void p3NetMgrIMPL::setAddrAssist(pqiAddrAssist *dhtStun, pqiAddrAssist *proxyStun) void p3NetMgrIMPL::setAddrAssist(pqiAddrAssist *dhtStun, pqiAddrAssist *proxyStun)
{ {
@ -1020,18 +1016,40 @@ bool p3NetMgrIMPL::checkNetAddress()
} }
else 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. /* TODO: Sat Oct 24 15:51:24 CEST 2015 The fact of having just one local
std::list<sockaddr_storage> addrs; * address is a flawed assumption, this should be redesigned as soon as
std::list<sockaddr_storage>::iterator it; * possible. It will require complete reenginering of the network layer
* code. */
std::vector<sockaddr_storage> addrs;
if (getLocalAddresses(addrs)) if (getLocalAddresses(addrs))
for(it = addrs.begin(); (it != addrs.end() && !validAddr); ++it)
if(sockaddr_storage_isValidNet(*it) && !sockaddr_storage_isLoopbackNet(*it))
{ {
prefAddr = *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 = addr;
validAddr = true; validAddr = true;
#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) break;
std::cout << "p3NetMgrIMPL::checkNetAddress() prefAddr: " << sockaddr_storage_iptostring(prefAddr) << std::endl; }
#endif }
/* 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 "util/rsnet.h"
#include "serialiser/rstlvaddrs.h" #include "serialiser/rstlvaddrs.h"
#define MAX_ADDRESS_LIST_SIZE 4 #define MAX_ADDRESS_LIST_SIZE 10
class pqiIpAddress class pqiIpAddress
{ {

View File

@ -3,7 +3,8 @@
* *
* 3P/PQI network interface for RetroShare. * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * 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> # include <net/if.h>
#endif // WINDOWS_SYS #endif // WINDOWS_SYS
bool getLocalAddresses(std::list<sockaddr_storage> & addrs) bool getLocalAddresses(std::vector<sockaddr_storage>& addrs)
{ {
addrs.clear(); addrs.clear();

View File

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

View File

@ -3,7 +3,8 @@
* *
* Services for RetroShare. * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@ -25,11 +26,15 @@
#include "services/p3discovery2.h" #include "services/p3discovery2.h"
#include "pqi/p3peermgr.h" #include "pqi/p3peermgr.h"
#include "pqi/pqinetwork.h" // for getLocalAddresses
#include "util/rsversioninfo.h" #include "util/rsversioninfo.h"
#include "retroshare/rsiface.h" #include "retroshare/rsiface.h"
#include "rsserver/p3face.h" #include "rsserver/p3face.h"
#include <vector> // for std::vector
#include <algorithm> // for std::random_shuffle
// Interface pointer. // Interface pointer.
RsDisc *rsDisc = NULL; RsDisc *rsDisc = NULL;
@ -38,7 +43,9 @@ RsDisc *rsDisc = NULL;
* #define P3DISC_DEBUG 1 * #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(); pkt->clear();
@ -343,8 +350,54 @@ void p3discovery2::sendOwnContactInfo(const SSLID &sslid)
peerState detail; 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(); 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->version = RsUtil::retroshareVersion();
pkt->PeerId(sslid); pkt->PeerId(sslid);
@ -433,7 +486,8 @@ void p3discovery2::recvOwnContactInfo(const SSLID &fromId, const RsDiscContactIt
void p3discovery2::updatePeerAddresses(const RsDiscContactItem *item) void p3discovery2::updatePeerAddresses(const RsDiscContactItem *item)
{ {
if (item->isHidden) if (item->isHidden)
mPeerMgr->setHiddenDomainPort(item->sslId, item->hiddenAddr, item->hiddenPort); mPeerMgr->setHiddenDomainPort(item->sslId, item->hiddenAddr,
item->hiddenPort);
else else
{ {
mPeerMgr->setDynDNS(item->sslId, item->dyndns); mPeerMgr->setDynDNS(item->sslId, item->dyndns);
@ -447,8 +501,19 @@ void p3discovery2::updatePeerAddressList(const RsDiscContactItem *item)
if (item->isHidden) 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; pqiIpAddrSet addrsFromPeer;
addrsFromPeer.mLocal.extractFromTlv(item->localAddrList); addrsFromPeer.mLocal.extractFromTlv(item->localAddrList);
addrsFromPeer.mExt.extractFromTlv(item->extAddrList); addrsFromPeer.mExt.extractFromTlv(item->extAddrList);
@ -472,12 +537,11 @@ void p3discovery2::sendPGPList(const SSLID &toId)
{ {
updatePgpFriendList(); updatePgpFriendList();
RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ RS_STACK_MUTEX(mDiscMtx);
#ifdef P3DISC_DEBUG #ifdef P3DISC_DEBUG
std::cerr << "p3discovery2::sendPGPList() to " << toId; std::cerr << "p3discovery2::sendPGPList() to " << toId << std::endl;
std::cerr << std::endl;
#endif #endif
RsDiscPgpListItem *pkt = new RsDiscPgpListItem(); RsDiscPgpListItem *pkt = new RsDiscPgpListItem();
@ -508,7 +572,7 @@ void p3discovery2::updatePgpFriendList()
std::cerr << std::endl; std::cerr << std::endl;
#endif #endif
RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ RS_STACK_MUTEX(mDiscMtx);
#define PGP_MAX_UPDATE_PERIOD 300 #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) 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 (item->sslId == rsPeers->getOwnId())
{ {
if(sockaddr_storage_isExternalNet(item->currentConnectAddress.addr)) if(sockaddr_storage_isExternalNet(item->currentConnectAddress.addr))
mPeerMgr->addCandidateForOwnExternalAddress(item->PeerId(), item->currentConnectAddress.addr) ; mPeerMgr->addCandidateForOwnExternalAddress(
#ifdef P3DISC_DEBUG item->PeerId(), item->currentConnectAddress.addr);
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; delete item;
return; return;
} }
/* */
std::map<PGPID, DiscPgpInfo>::iterator it; std::map<PGPID, DiscPgpInfo>::iterator it;
it = mFriendList.find(item->pgpId); it = mFriendList.find(item->pgpId);
if (it == mFriendList.end()) if (it == mFriendList.end())
@ -895,7 +953,8 @@ void p3discovery2::processContactInfo(const SSLID &fromId, const RsDiscContactIt
std::cerr << std::endl; std::cerr << std::endl;
#endif #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 * 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 // 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 // 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); updatePeerAddresses(item);
} }
} }

View File

@ -4,6 +4,7 @@
* Universal Networking Header for RetroShare. * Universal Networking Header for RetroShare.
* *
* Copyright 2007-2008 by Robert Fernie. * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@ -151,21 +152,21 @@ bool isPrivateNet(const struct in_addr *addr)
{ {
in_addr_t taddr = ntohl(addr->s_addr); in_addr_t taddr = ntohl(addr->s_addr);
// 10.0.0.0/8 if ( (taddr>>24 == 10) || // 10.0.0.0/8
// 172.16.0.0/12 (taddr>>20 == (172<<4 | 16>>4)) || // 172.16.0.0/12
// 192.168.0.0/16 (taddr>>16 == (192<<8 | 168)) || // 192.168.0.0/16
// 169.254.0.0/16 (taddr>>16 == (169<<8 | 254)) ) // 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)))
{
return true; 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) bool isExternalNet(const struct in_addr *addr)

View File

@ -4,6 +4,7 @@
* Universal Networking Header for RetroShare. * Universal Networking Header for RetroShare.
* *
* Copyright 2004-2006 by Robert Fernie. * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * 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 isValidNet(const struct in_addr *addr);
bool isLoopbackNet(const struct in_addr *addr); bool isLoopbackNet(const struct in_addr *addr);
bool isPrivateNet(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); bool isExternalNet(const struct in_addr *addr);
// uses a re-entrant version of gethostbyname // 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_isValidNet(const struct sockaddr_storage &addr);
bool sockaddr_storage_isLoopbackNet(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_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 sockaddr_storage_isExternalNet(const struct sockaddr_storage &addr);
bool rs_inet_ntop(const sockaddr_storage &addr, std::string &dst); bool rs_inet_ntop(const sockaddr_storage &addr, std::string &dst);

View File

@ -4,6 +4,7 @@
* sockaddr_storage functions for RetroShare. * sockaddr_storage functions for RetroShare.
* *
* Copyright 2013-2013 by Robert Fernie. * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * 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; std::stringstream output;
output << "sockaddr_storage_dump(addr) "; output << "sockaddr_storage_dump(addr) ";
switch (addr.ss_family){ switch (addr.ss_family)
{
case AF_INET: case AF_INET:
{ {
const sockaddr_in * in = (const sockaddr_in *) & addr; 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 ) for( uint32_t i = 0; i < sizeof(addr); ++i )
output << std::setw(2) << std::setfill('0') << std::hex << +buf[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 // The unary +buf[i] operation forces a no-op type conversion to an int with the correct sign
}} }
}
if(outputString) if(outputString)
{ {
@ -578,6 +581,31 @@ bool sockaddr_storage_isPrivateNet(const struct sockaddr_storage &addr)
return false; 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) bool sockaddr_storage_isExternalNet(const struct sockaddr_storage &addr)
{ {