Implement IPv6 listening

With this commit IPv6-v3 surpass v0.6-IPv6-2 in term of features
  obsoleting it.
p3BitDht handle gracefully unwanted non IPv4 addresses
rsUdpStack handle gracefully unwanted non IPv4 addresses
pqissludp handle gracefully unwanted non IPv4 addresses
Move single address limitation workaround from
  p3discovery2::sendOwnContactInfo to better
  place p3PeerMgrIMPL::UpdateOwnAddress this way local address list is
  queried less often and only id there is some suggestion that it may
  have changed (probably ir will not be called all the times there is a
  changes in local network interfaces but is good enough)
Implement crossplatform rs_setsockopt to avoid too much ifdef around
Implement sockaddr_storage_copy to safely copy sockaddr_storage objects
This commit is contained in:
Gioacchino Mazzurco 2018-02-24 14:07:25 +01:00
parent b3c7d195c8
commit 4a138e07b9
No known key found for this signature in database
GPG Key ID: A1FBCA3872E87051
14 changed files with 618 additions and 378 deletions

View File

@ -4,6 +4,7 @@
* BitDht interface for RetroShare.
*
* Copyright 2009-2010 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
@ -184,18 +185,24 @@ bool p3BitDht::dropPeer(const RsPeerId& pid)
********************************* Basic Peer Details *************************************
******************************************************************************************/
int p3BitDht::addBadPeer(const struct sockaddr_storage &addr, uint32_t /*reason*/, uint32_t /*flags*/, uint32_t /*age*/)
int p3BitDht::addBadPeer( const sockaddr_storage &addr, uint32_t /*reason*/,
uint32_t /*flags*/, uint32_t /*age*/ )
{
//mUdpBitDht->updateKnownPeer(&id, 0, bdflags);
struct sockaddr_in addrv4;
if (addr.ss_family != AF_INET)
sockaddr_in addrv4;
sockaddr_storage tmpaddr;
sockaddr_storage_copy(addr, tmpaddr);
if(!sockaddr_storage_ipv6_to_ipv4(tmpaddr))
{
std::cerr << "p3BitDht::addBadPeer() cannot handle IPV6 Yet, aborting";
std::cerr << std::endl;
abort();
std::cerr << __PRETTY_FUNCTION__ << " Error: got non IPv4 address!"
<< std::endl;
sockaddr_storage_dump(addr);
print_stacktrace();
return -EINVAL;
}
struct sockaddr_in *ap = (struct sockaddr_in *) &addr;
struct sockaddr_in *ap = (struct sockaddr_in *) &tmpaddr;
// convert.
addrv4.sin_family = ap->sin_family;
@ -216,39 +223,30 @@ 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)
int p3BitDht::addKnownPeer( const RsPeerId &pid,
const sockaddr_storage &addr, uint32_t flags )
{
struct sockaddr_in addrv4;
sockaddr_clear(&addrv4);
sockaddr_in addrv4;
sockaddr_clear(&addrv4);
if (addr.ss_family != AF_INET)
{
if(addr.ss_family != AF_UNSPEC)
{
std::cerr << "p3BitDht::addKnownPeer() Warning! Non IPv4 Address - Cannot handle IPV6 Yet. addr.ss_family=" << addr.ss_family;
std::cerr << std::endl;
}
if (flags & NETASSIST_KNOWN_PEER_ONLINE)
{
std::cerr << "p3BitDht::addKnownPeer() Non IPv4 Address & ONLINE. Abort()ing.";
std::cerr << std::endl;
abort();
}
}
else
sockaddr_storage tmpaddr;
sockaddr_storage_copy(addr, tmpaddr);
if( !sockaddr_storage_isnull(addr) &&
!sockaddr_storage_ipv6_to_ipv4(tmpaddr) )
{
// convert.
struct sockaddr_in *ap = (struct sockaddr_in *) &addr;
addrv4.sin_family = ap->sin_family;
addrv4.sin_addr = ap->sin_addr;
addrv4.sin_port = ap->sin_port;
std::cerr << __PRETTY_FUNCTION__ << " Error: got non IPv4 address!"
<< std::endl;
sockaddr_storage_dump(addr);
print_stacktrace();
return -EINVAL;
}
// convert.
struct sockaddr_in *ap = (struct sockaddr_in *) &tmpaddr;
addrv4.sin_family = ap->sin_family;
addrv4.sin_addr = ap->sin_addr;
addrv4.sin_port = ap->sin_port;
int p3type = 0;
int bdflags = 0;
bdId id;
@ -295,7 +293,7 @@ int p3BitDht::addKnownPeer(const RsPeerId &pid, const struct sockaddr_storage &a
if (!isOwnId)
{
RsStackMutex stack(dhtMtx); /********* LOCKED *********/
RS_STACK_MUTEX(dhtMtx);
DhtPeerDetails *dpd = addInternalPeer_locked(pid, p3type);

View File

@ -1038,12 +1038,15 @@ bool p3NetMgrIMPL::checkNetAddress()
}
/* If no satisfactory local address has been found yet relax and
* accept also link local addresses */
* accept also IPv4 link local addresses, IPv6 link local is not
* accepted because of sin6_scope_id that depends on the host using
* it as an outgoing connection endpoint */
if(!validAddr) for (auto it = addrs.begin(); it!=addrs.end(); ++it)
{
sockaddr_storage& addr(*it);
if( sockaddr_storage_isValidNet(addr) &&
!sockaddr_storage_isLoopbackNet(addr) )
!sockaddr_storage_isLoopbackNet(addr) &&
!sockaddr_storage_ipv6_isLinkLocalNet(addr) )
{
prefAddr = addr;
validAddr = true;

View File

@ -4,6 +4,7 @@
* 3P/PQI network interface for RetroShare.
*
* Copyright 2007-2011 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
@ -23,6 +24,9 @@
*
*/
#include <vector> // for std::vector
#include <algorithm> // for std::random_shuffle
#include "rsserver/p3face.h"
#include "util/rsnet.h"
#include "pqi/authgpg.h"
@ -32,6 +36,7 @@
#include "pqi/p3linkmgr.h"
#include "pqi/p3netmgr.h"
#include "pqi/p3historymgr.h"
#include "pqi/pqinetwork.h" // for getLocalAddresses
//#include "pqi/p3dhtmgr.h" // Only need it for constants.
//#include "tcponudp/tou.h"
@ -1227,38 +1232,85 @@ void p3PeerMgrIMPL::printPeerLists(std::ostream &out)
* as it doesn't call back to there.
*/
bool p3PeerMgrIMPL::UpdateOwnAddress(const struct sockaddr_storage &localAddr, const struct sockaddr_storage &extAddr)
bool p3PeerMgrIMPL::UpdateOwnAddress( const sockaddr_storage& localAddr,
const sockaddr_storage& extAddr )
{
#ifdef PEER_DEBUG
std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress(";
std::cerr << sockaddr_storage_tostring(localAddr);
std::cerr << ", ";
std::cerr << sockaddr_storage_tostring(extAddr);
std::cerr << ")" << std::endl;
std::cerr << "p3PeerMgrIMPL::UpdateOwnAddress("
<< sockaddr_storage_tostring(localAddr) << ", "
<< sockaddr_storage_tostring(extAddr) << ")" << std::endl;
#endif
if((rsBanList != NULL) && !rsBanList->isAddressAccepted(localAddr, RSBANLIST_CHECKING_FLAGS_BLACKLIST))
{
std::cerr << "(SS) Trying to set own IP to a banned IP " << sockaddr_storage_iptostring(localAddr) << ". This probably means that a friend in under traffic re-routing attack." << std::endl;
return false ;
}
if( rsBanList &&
!rsBanList->isAddressAccepted(localAddr,
RSBANLIST_CHECKING_FLAGS_BLACKLIST) )
{
std::cerr << "(SS) Trying to set own IP to a banned IP "
<< sockaddr_storage_iptostring(localAddr) << ". This probably"
<< "means that a friend in under traffic re-routing attack."
<< std::endl;
return false;
}
{
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
{
RS_STACK_MUTEX(mPeerMtx);
//update ip address list
pqiIpAddress ipAddressTimed;
ipAddressTimed.mAddr = localAddr;
ipAddressTimed.mSeenTime = time(NULL);
ipAddressTimed.mSrc = 0 ;
mOwnState.ipAddrs.updateLocalAddrs(ipAddressTimed);
//update ip address list
pqiIpAddress ipAddressTimed;
ipAddressTimed.mAddr = localAddr;
ipAddressTimed.mSeenTime = time(NULL);
ipAddressTimed.mSrc = 0;
mOwnState.ipAddrs.updateLocalAddrs(ipAddressTimed);
mOwnState.localaddr = localAddr;
}
if(!mOwnState.hiddenNode)
{
/* 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(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) &&
/* Avoid IPv6 link local addresses as we don't have
* implemented the logic needed to handle sin6_scope_id.
* To properly handle sin6_scope_id it would probably
* require deep reenginering of the RetroShare
* networking stack */
!sockaddr_storage_ipv6_isLinkLocalNet(addr) )
{
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(localAddr) );
pqiIp.mSeenTime = time(nullptr);
pqiIp.mSrc = 0;
mOwnState.ipAddrs.updateLocalAddrs(pqiIp);
}
}
}
}
mOwnState.localaddr = localAddr;
}
{
RsStackMutex stack(mPeerMtx); /****** STACK LOCK MUTEX *******/
{
RS_STACK_MUTEX(mPeerMtx);
//update ip address list
pqiIpAddress ipAddressTimed;

View File

@ -41,6 +41,7 @@
#include "util/rsdebug.h"
#include "util/rsstring.h"
#include "util/rsnet.h"
#include "util/stacktrace.h"
static struct RsLog::logInfo pqinetzoneInfo = {RsLog::Default, "pqinet"};
#define pqinetzone &pqinetzoneInfo
@ -335,15 +336,17 @@ bool getLocalAddresses(std::vector<sockaddr_storage>& addrs)
struct ifaddrs *ifsaddrs, *ifa;
if(getifaddrs(&ifsaddrs) != 0)
{
std::cerr << "FATAL ERROR: getLocalAddresses failed!" << std::endl;
return false ;
std::cerr << __PRETTY_FUNCTION__ << " FATAL ERROR: " << errno << " "
<< strerror(errno) << std::endl;
print_stacktrace();
return false;
}
for ( ifa = ifsaddrs; ifa; ifa = ifa->ifa_next )
if ( ifa->ifa_addr && (ifa->ifa_flags & IFF_UP) )
{
sockaddr_storage tmp;
sockaddr_storage_clear(tmp);
if (sockaddr_storage_copyip(tmp, * reinterpret_cast<sockaddr_storage*>(ifa->ifa_addr)))
if (sockaddr_storage_copyip(tmp, *reinterpret_cast<sockaddr_storage*>(ifa->ifa_addr)))
addrs.push_back(tmp);
}
freeifaddrs(ifsaddrs);

View File

@ -60,14 +60,15 @@ static struct RsLog::logInfo pqisslzoneInfo = {RsLog::Default, "pqisslzone"};
#define PQISSL_PASSIVE 0x00
#define PQISSL_ACTIVE 0x01
#define PQISSL_DEBUG 1
#define PQISSL_LOG_DEBUG 1
const int PQISSL_LOCAL_FLAG = 0x01;
const int PQISSL_REMOTE_FLAG = 0x02;
const int PQISSL_UDP_FLAG = 0x02;
***********/
//#define PQISSL_DEBUG 1
//#define PQISSL_LOG_DEBUG 1
static const int PQISSL_MAX_READ_ZERO_COUNT = 20;
static const time_t PQISSL_MAX_READ_ZERO_TIME = 15; // 15 seconds of no data => reset. (atm HeartBeat pkt sent 5 secs)
@ -123,6 +124,7 @@ pqissl::pqissl(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm) :
int pqissl::connect(const struct sockaddr_storage &raddr)
{
RS_STACK_MUTEX(mSslMtx);
remote_addr = raddr;
return ConnectAttempt();
}
@ -171,12 +173,11 @@ int pqissl::close()
// put back on the listening queue.
int pqissl::reset()
{
RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/
RS_STACK_MUTEX(mSslMtx);
return reset_locked();
}
int pqissl::reset_locked()
int pqissl::reset_locked()
{
std::string outLog;
bool neededReset = false;
@ -355,7 +356,7 @@ int pqissl::status()
out += " active: \n";
// print out connection.
out += "Connected TO : " + PeerId() + "\n";
out += "Connected TO : " + PeerId().toStdString() + "\n";
// print out cipher.
rs_sprintf_append(out, "\t\tSSL Cipher:%s", SSL_get_cipher(ssl_connection));
rs_sprintf_append(out, " (%d:%d)", SSL_get_cipher_bits(ssl_connection, &alg), alg);
@ -551,7 +552,7 @@ int pqissl::Delay_Connection()
#ifdef PQISSL_LOG_DEBUG
{
std::string out;
rs_sprintf(out, "pqissl::Delay_Connection() Delaying Connection to %s for %lu seconds", PeerId().c_str(), mConnectDelay);
rs_sprintf(out, "pqissl::Delay_Connection() Delaying Connection to %s for %lu seconds", PeerId().toStdString(), mConnectDelay);
rslog(RSL_DEBUG_BASIC, pqisslzone, out);
}
#endif
@ -564,7 +565,7 @@ int pqissl::Delay_Connection()
#ifdef PQISSL_LOG_DEBUG
{
std::string out;
rs_sprintf(out, "pqissl::Delay_Connection() Connection to %s starting in %ld seconds", PeerId().c_str(), mConnectTS - time(NULL));
rs_sprintf(out, "pqissl::Delay_Connection() Connection to %s starting in %ld seconds", PeerId().toStdString(), mConnectTS - time(NULL));
rslog(RSL_DEBUG_BASIC, pqisslzone, out);
}
#endif
@ -710,10 +711,12 @@ int pqissl::Initiate_Connection()
* will support IPv6 only and not IPv4 */
#ifdef IPV6_V6ONLY
int no = 0;
err = setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&no, sizeof(no));
err = rs_setsockopt( osock, IPPROTO_IPV6, IPV6_V6ONLY,
reinterpret_cast<uint8_t*>(&no), sizeof(no) );
#ifdef PQISSL_DEBUG
if (err) std::cerr << __PRETTY_FUNCTION__
<< " Error setting IPv6 socket dual stack" << std::endl;
<< " Error setting IPv6 socket dual stack: "
<< errno << " " << strerror(errno) << std::endl;
else std::cerr << __PRETTY_FUNCTION__
<< " Setting IPv6 socket dual stack" << std::endl;
#endif // PQISSL_DEBUG
@ -1089,7 +1092,7 @@ int pqissl::Initiate_SSL_Connection()
return 1;
}
int pqissl::SSL_Connection_Complete()
int pqissl::SSL_Connection_Complete()
{
#ifdef PQISSL_LOG_DEBUG
rslog(RSL_DEBUG_BASIC, pqisslzone,
@ -1231,27 +1234,21 @@ int pqissl::Extract_Failed_SSL_Certificate()
int pqissl::Authorise_SSL_Connection()
int pqissl::Authorise_SSL_Connection()
{
#ifdef PQISSL_LOG_DEBUG
rslog(RSL_DEBUG_BASIC, pqisslzone,
"pqissl::Authorise_SSL_Connection()");
#ifdef PQISSL_DEBUG
std::cerr << __PRETTY_FUNCTION__ << std::endl;
#endif
if (time(NULL) > ssl_connect_timeout)
{
rslog(RSL_WARNING, pqisslzone,
"pqissl::Authorise_SSL_Connection() Connection Timed Out!");
/* as sockfd is valid, this should close it all up */
rslog(RSL_ALERT, pqisslzone, "pqissl::Authorise_Connection_Complete() -> calling reset()");
reset_locked();
if (time(NULL) > ssl_connect_timeout)
{
std::cerr << __PRETTY_FUNCTION__ << " Connection timed out reset!"
<< std::endl;
reset_locked();
}
int err;
if (0 >= (err = SSL_Connection_Complete()))
{
return err;
}
if (0 >= (err = SSL_Connection_Complete())) return err;
#ifdef PQISSL_LOG_DEBUG
rslog(RSL_DEBUG_BASIC, pqisslzone,
@ -1336,36 +1333,54 @@ int pqissl::Authorise_SSL_Connection()
/* This function is public, and callable from pqilistener - so must be mutex protected */
int pqissl::accept(SSL *ssl, int fd, const struct sockaddr_storage &foreign_addr) // initiate incoming connection.
int pqissl::accept( SSL *ssl, int fd,
const sockaddr_storage &foreign_addr)
{
#ifdef PQISSL_DEBUG
std::cerr << "pqissl::accept()";
std::cerr << std::endl;
std::cerr << __PRETTY_FUNCTION__ << std::endl;
#endif
RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/
RS_STACK_MUTEX(mSslMtx);
return accept_locked(ssl, fd, foreign_addr);
}
int pqissl::accept_locked(SSL *ssl, int fd, const struct sockaddr_storage &foreign_addr) // initiate incoming connection.
int pqissl::accept_locked( SSL *ssl, int fd,
const sockaddr_storage &foreign_addr )
{
uint32_t check_result;
uint32_t checking_flags = RSBANLIST_CHECKING_FLAGS_BLACKLIST;
if (rsPeers->servicePermissionFlags(PeerId()) & RS_NODE_PERM_REQUIRE_WL)
checking_flags |= RSBANLIST_CHECKING_FLAGS_WHITELIST;
#ifdef PQISSL_DEBUG
std::cerr << __PRETTY_FUNCTION__ << std::endl;
#endif
if(rsBanList!=NULL && !rsBanList->isAddressAccepted(foreign_addr,checking_flags,&check_result))
{
std::cerr << "(SS) refusing incoming SSL connection from blacklisted foreign address " << sockaddr_storage_iptostring(foreign_addr)
<< ". Reason: " << check_result << "." << std::endl;
RsServer::notify()->AddFeedItem(RS_FEED_ITEM_SEC_IP_BLACKLISTED, PeerId().toStdString(), sockaddr_storage_iptostring(foreign_addr), "", "", check_result);
uint32_t check_result;
uint32_t checking_flags = RSBANLIST_CHECKING_FLAGS_BLACKLIST;
if (rsPeers->servicePermissionFlags(PeerId()) & RS_NODE_PERM_REQUIRE_WL)
checking_flags |= RSBANLIST_CHECKING_FLAGS_WHITELIST;
if( rsBanList && !rsBanList->isAddressAccepted( foreign_addr,
checking_flags,
&check_result ) )
{
std::cerr << __PRETTY_FUNCTION__
<< " (SS) refusing incoming SSL connection from blacklisted "
<< "foreign address "
<< sockaddr_storage_iptostring(foreign_addr)
<< ". Reason: " << check_result << "." << std::endl;
RsServer::notify()->AddFeedItem(
RS_FEED_ITEM_SEC_IP_BLACKLISTED,
PeerId().toStdString(),
sockaddr_storage_iptostring(foreign_addr), "", "",
check_result);
reset_locked();
return -1;
}
return -1;
}
if (waiting != WAITING_NOT)
{
rslog(RSL_WARNING, pqisslzone, "pqissl::accept() Peer: " + PeerId().toStdString() + " - Two connections in progress - Shut 1 down!");
std::cerr << __PRETTY_FUNCTION__ << " Peer: " << PeerId().toStdString()
<< " - Two connections in progress - Shut 1 down!"
<< std::endl;
// outgoing connection in progress.
// shut this baby down.
@ -1376,70 +1391,51 @@ int pqissl::accept_locked(SSL *ssl, int fd, const struct sockaddr_storage &forei
switch(waiting)
{
case WAITING_SOCK_CONNECT:
#ifdef PQISSL_LOG_DEBUG
rslog(RSL_DEBUG_BASIC, pqisslzone,
"pqissl::accept() STATE = Waiting Sock Connect - close the socket");
#ifdef PQISSL_DEBUG
std::cerr << __PRETTY_FUNCTION__ << " STATE = Waiting Sock Connect "
<< "- close the socket" << std::endl;
#endif
break;
case WAITING_SSL_CONNECTION:
#ifdef PQISSL_LOG_DEBUG
rslog(RSL_DEBUG_BASIC, pqisslzone,
"pqissl::accept() STATE = Waiting SSL Connection - close sockfd + ssl_conn");
#ifdef PQISSL_DEBUG
std::cerr << __PRETTY_FUNCTION__ << " STATE = Waiting SSL "
<< "Connection - close sockfd + ssl_conn" << std::endl;
#endif
break;
case WAITING_SSL_AUTHORISE:
#ifdef PQISSL_LOG_DEBUG
rslog(RSL_DEBUG_BASIC, pqisslzone,
"pqissl::accept() STATE = Waiting SSL Authorise - close sockfd + ssl_conn");
#ifdef PQISSL_DEBUG
std::cerr << __PRETTY_FUNCTION__ << " STATE = Waiting SSL Authorise"
<< " - close sockfd + ssl_conn" << std::endl;
#endif
break;
case WAITING_FAIL_INTERFACE:
#ifdef PQISSL_LOG_DEBUG
rslog(RSL_DEBUG_BASIC, pqisslzone,
"pqissl::accept() STATE = Failed, ignore?");
#ifdef PQISSL_DEBUG
std::cerr << __PRETTY_FUNCTION__ << " STATE = Failed, ignore?"
<< std::endl;
#endif
break;
default:
rslog(RSL_ALERT, pqisslzone,
"pqissl::accept() STATE = Unknown - ignore?");
rslog(RSL_ALERT, pqisslzone, "pqissl::accept() -> calling reset()");
std::cerr << __PRETTY_FUNCTION__ << " STATE = Unknown - resetting!"
<< std::endl;
reset_locked();
break;
}
//waiting = WAITING_FAIL_INTERFACE;
//return -1;
}
/* shutdown existing - in all cases use the new one */
if ((ssl_connection) && (ssl_connection != ssl))
{
rslog(RSL_ALERT, pqisslzone,
"pqissl::accept() closing Previous/Existing ssl_connection");
std::cerr << __PRETTY_FUNCTION__
<< " closing Previous/Existing ssl_connection" << std::endl;
SSL_shutdown(ssl_connection);
SSL_free (ssl_connection);
}
if ((sockfd > -1) && (sockfd != fd))
{
rslog(RSL_ALERT, pqisslzone,
"pqissl::accept() closing Previous/Existing sockfd");
std::cerr << __PRETTY_FUNCTION__ << " closing Previous/Existing sockfd"
<< std::endl;
net_internal_close(sockfd);
}
@ -1452,54 +1448,39 @@ int pqissl::accept_locked(SSL *ssl, int fd, const struct sockaddr_storage &forei
/* if we connected - then just writing the same over,
* but if from ssllistener then we need to save the address.
*/
remote_addr = foreign_addr;
sockaddr_storage_copy(foreign_addr, remote_addr);
/* check whether it is on the same LAN */
struct sockaddr_storage localaddr;
mLinkMgr->getLocalAddress(localaddr);
std::cerr << __PRETTY_FUNCTION__ << " SUCCESSFUL connection to: "
<< PeerId().toStdString() << " remoteaddr: "
<< sockaddr_storage_iptostring(remote_addr) << std::endl;
#ifdef PQISSL_DEBUG
{
std::string out = "pqissl::accept() SUCCESSFUL connection to: " + PeerId().toStdString();
out += " localaddr: " + sockaddr_storage_iptostring(localaddr);
out += " remoteaddr: " + sockaddr_storage_iptostring(remote_addr);
rslog(RSL_WARNING, pqisslzone, out);
}
// establish the ssl details.
// cipher name.
int err;
#ifdef PQISSL_LOG_DEBUG
{
int alg;
std::string out;
rs_sprintf(out, "SSL Cipher:%s\n", SSL_get_cipher(ssl));
rs_sprintf_append(out, "SSL Cipher Bits:%d - %d\n", SSL_get_cipher_bits(ssl, &alg), alg);
rs_sprintf_append(out, "SSL Cipher Version:%s\n", SSL_get_cipher_version(ssl));
rslog(RSL_DEBUG_BASIC, pqisslzone, out);
int alg;
std::cerr << __PRETTY_FUNCTION__ << "SSL Cipher: "
<< SSL_get_cipher(ssl) << std::endl << "SSL Cipher Bits: "
<< SSL_get_cipher_bits(ssl, &alg) << " - " << alg
<< std::endl;
}
#endif
// make non-blocking / or check.....
if ((err = net_internal_fcntl_nonblock(sockfd)) < 0)
int err;
if ((err = net_internal_fcntl_nonblock(sockfd)) < 0)
{
rslog(RSL_ALERT, pqisslzone, "Error: Cannot make socket NON-Blocking: ");
std::cerr << __PRETTY_FUNCTION__ << "Cannot make socket NON-Blocking "
<< "reset!" << std::endl;
active = false;
waiting = WAITING_FAIL_INTERFACE;
// failed completely.
rslog(RSL_ALERT, pqisslzone, "pqissl::accept() -> calling reset()");
waiting = WAITING_FAIL_INTERFACE; // failed completely.
reset_locked();
return -1;
}
else
{
#ifdef PQISSL_LOG_DEBUG
rslog(RSL_DEBUG_BASIC, pqisslzone, "pqissl::accept() Socket Made Non-Blocking!");
#ifdef PQISSL_DEBUG
else std::cerr << __PRETTY_FUNCTION__ << " Socket made non-nlocking!"
<< std::endl;
#endif
}
// we want to continue listening - incase this socket is crap, and they try again.
//stoplistening();
@ -1508,15 +1489,16 @@ int pqissl::accept_locked(SSL *ssl, int fd, const struct sockaddr_storage &forei
waiting = WAITING_NOT;
#ifdef PQISSL_DEBUG
std::cerr << "pqissl::accept_locked() connection complete - notifying parent";
std::cerr << std::endl;
std::cerr << __PRETTY_FUNCTION__ << "connection complete - notifying parent"
<< std::endl;
#endif
// Notify the pqiperson.... (Both Connect/Receive)
if (parent())
{
struct sockaddr_storage addr = remote_addr;
parent() -> notifyEvent(this, NET_CONNECT_SUCCESS, addr);
// Is the copy necessary?
sockaddr_storage addr; sockaddr_storage_copy(remote_addr, addr);
parent()->notifyEvent(this, NET_CONNECT_SUCCESS, addr);
}
return 1;
}
@ -1610,31 +1592,35 @@ int pqissl::senddata(void *data, int len)
return tmppktlen;
}
int pqissl::readdata(void *data, int len)
int pqissl::readdata(void *data, int len)
{
RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/
RS_STACK_MUTEX(mSslMtx);
#ifdef PQISSL_DEBUG
std::cout << "Reading data thread=" << pthread_self() << ", ssl=" << (void*)this << std::endl ;
std::cout << "Reading data thread=" << pthread_self() << ", ssl="
<< (void*)this << std::endl;
#endif
// Safety check. Apparently this avoids some SIGSEGV.
//
if (ssl_connection == NULL)
return -1 ;
if (ssl_connection == NULL) return -1;
// There is a do, because packets can be splitted into multiple ssl buffers
// when they are larger than 16384 bytes. Such packets have to be read in
// multiple slices.
do
{
int tmppktlen ;
int tmppktlen;
#ifdef PQISSL_DEBUG
std::cerr << "calling SSL_read. len=" << len << ", total_len=" << total_len << std::endl ;
std::cerr << "calling SSL_read. len=" << len << ", total_len="
<< total_len << std::endl;
#endif
ERR_clear_error() ;
tmppktlen = SSL_read(ssl_connection, (void*)( &(((uint8_t*)data)[total_len])), len-total_len) ;
ERR_clear_error();
tmppktlen = SSL_read(ssl_connection,
(void*)( &(((uint8_t*)data)[total_len])),
len-total_len);
#ifdef PQISSL_DEBUG
std::cerr << "have read " << tmppktlen << " bytes" << std::endl ;
std::cerr << "data[0] = "
@ -1649,7 +1635,6 @@ int pqissl::readdata(void *data, int len)
#endif
// Need to catch errors.....
//
if (tmppktlen <= 0) // probably needs a reset.
{
std::string out;

View File

@ -119,12 +119,9 @@ virtual bool bandwidthLimited() { return true ; }
public:
/* Completion of the SSL connection,
* this is public, so it can be called by
* the listener (should make friends??)
*/
/// initiate incoming connection.
int accept(SSL *ssl, int fd, const struct sockaddr_storage &foreign_addr);
int accept(SSL *ssl, int fd, const struct sockaddr_storage &foreign_addr);
void getCryptoParams(RsPeerCryptoParams& params) ;
bool actAsServer();
@ -140,7 +137,10 @@ protected:
RsMutex mSslMtx; /**** MUTEX protects data and fn below ****/
virtual int reset_locked();
int accept_locked(SSL *ssl, int fd, const struct sockaddr_storage &foreign_addr);
/// initiate incoming connection.
int accept_locked( SSL *ssl, int fd,
const sockaddr_storage& foreign_addr );
// A little bit of information to describe
// the SSL state, this is needed

View File

@ -4,6 +4,7 @@
* 3P/PQI network interface 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
@ -103,17 +104,27 @@ int pqissllistenbase::status()
return 1;
}
int pqissllistenbase::setuplisten()
int pqissllistenbase::setuplisten()
{
int err;
if (active)
return -1;
int err;
if (active) return -1;
lsock = socket(PF_INET6, SOCK_STREAM, 0);
#ifdef IPV6_V6ONLY
int no = 0;
err = rs_setsockopt(lsock, IPPROTO_IPV6, IPV6_V6ONLY,
reinterpret_cast<uint8_t*>(&no), sizeof(no));
if (err) std::cerr << __PRETTY_FUNCTION__
<< ": Error setting IPv6 socket dual stack" << std::endl;
else std::cerr << __PRETTY_FUNCTION__
<< ": Success setting IPv6 socket dual stack" << std::endl;
#endif // IPV6_V6ONLY
lsock = socket(PF_INET, SOCK_STREAM, 0);
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
#ifndef WINDOWS_SYS // ie UNIX
if (lsock < 0)
{
if (lsock < 0)
{
pqioutput(PQL_ALERT, pqissllistenzone,
"pqissllistenbase::setuplisten() Cannot Open Socket!");
@ -199,10 +210,14 @@ int pqissllistenbase::setuplisten()
#ifdef OPEN_UNIVERSAL_PORT
struct sockaddr_storage tmpaddr = laddr;
if (!mPeerMgr->isHidden()) sockaddr_storage_zeroip(tmpaddr);
if (0 != (err = universal_bind(lsock, (struct sockaddr *) &tmpaddr, sizeof(tmpaddr))))
if (!mPeerMgr->isHidden())
{
tmpaddr.ss_family = PF_INET6;
sockaddr_storage_zeroip(tmpaddr);
}
if (0 != (err = rs_bind(lsock, tmpaddr)))
#else
if (0 != (err = universal_bind(lsock, (struct sockaddr *) &laddr, sizeof(laddr))))
if (0 != (err = universal_bind(lsock, laddr)))
#endif
{
std::string out = "pqissllistenbase::setuplisten() Cannot Bind to Local Address!\n";

View File

@ -250,22 +250,38 @@ int pqissludp::Initiate_Connection()
{
std::cerr << "CONVERTING ALL ADDRESSES TO IPV4: TODO make IPV6";
std::cerr << std::endl;
struct sockaddr_in srcaddr;
struct sockaddr_in proxyaddr;
struct sockaddr_in remoteaddr;
if ((mConnectSrcAddr.ss_family != AF_INET) ||
(mConnectProxyAddr.ss_family != AF_INET) ||
(remote_addr.ss_family != AF_INET))
bool nonIpV4 = false;
if(!sockaddr_storage_ipv6_to_ipv4(remote_addr))
{
std::cerr << "Error One Address is not IPv4. aborting";
std::cerr << std::endl;
abort();
nonIpV4 = true;
std::cerr << __PRETTY_FUNCTION__ << "Error: remote_addr is not "
<< "valid IPv4!" << std::endl;
sockaddr_storage_dump(remote_addr);
}
if(!sockaddr_storage_ipv6_to_ipv4(mConnectSrcAddr))
{
nonIpV4 = true;
std::cerr << __PRETTY_FUNCTION__ << "Error: mConnectSrcAddr is "
<< "not valid IPv4!" << std::endl;
sockaddr_storage_dump(mConnectSrcAddr);
}
if(!sockaddr_storage_ipv6_to_ipv4(mConnectProxyAddr))
{
nonIpV4 = true;
std::cerr << __PRETTY_FUNCTION__ << "Error: mConnectProxyAddr "
<< "is not valid IPv4!" << std::endl;
sockaddr_storage_dump(mConnectProxyAddr);
}
if(!nonIpV4)
{
print_stacktrace();
return -EINVAL;
}
struct sockaddr_in *rap = (struct sockaddr_in *) &remote_addr;
struct sockaddr_in *pap = (struct sockaddr_in *) &mConnectProxyAddr;
struct sockaddr_in *sap = (struct sockaddr_in *) &mConnectSrcAddr;

View File

@ -4,6 +4,7 @@
* RetroShare C++ Interface.
*
* Copyright 2004-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
@ -900,68 +901,33 @@ bool p3Peers::setHiddenNode(const RsPeerId &id, const std::string &address, uin
return true;
}
bool p3Peers::setLocalAddress(const RsPeerId &id, const std::string &addr_str, uint16_t port)
bool p3Peers::setLocalAddress(const RsPeerId &id,
const std::string &addr_str, uint16_t port)
{
#ifdef P3PEERS_DEBUG
std::cerr << "p3Peers::setLocalAddress() " << id << std::endl;
std::cerr << __PRETTY_FUNCTION__ << " " << id << " " << addr_str << " "
<< port << std::endl;
#endif
if(port < 1024)
{
std::cerr << "(EE) attempt to use a port that is reserved to the system: " << port << std::endl;
return false ;
}
struct sockaddr_storage addr;
struct sockaddr_in *addrv4p = (struct sockaddr_in *) &addr;
addrv4p->sin_family = AF_INET;
addrv4p->sin_port = htons(port);
int ret = 1;
/********************************** WINDOWS/UNIX SPECIFIC PART *******************/
#ifndef WINDOWS_SYS
if (ret && (0 != inet_aton(addr_str.c_str(), &(addrv4p->sin_addr))))
#else
addrv4p->sin_addr.s_addr = inet_addr(addr_str.c_str());
if (ret)
#endif
/********************************** WINDOWS/UNIX SPECIFIC PART *******************/
{
return mPeerMgr->setLocalAddress(id, addr);
}
sockaddr_storage addr;
if (sockaddr_storage_inet_pton(addr, addr_str))
if (sockaddr_storage_setport(addr, port))
return mPeerMgr->setLocalAddress(id, addr);
return false;
}
bool p3Peers::setExtAddress(const RsPeerId &id, const std::string &addr_str, uint16_t port)
bool p3Peers::setExtAddress(const RsPeerId &id,
const std::string &addr_str, uint16_t port)
{
#ifdef P3PEERS_DEBUG
std::cerr << "p3Peers::setExtAddress() " << id << std::endl;
std::cerr << __PRETTY_FUNCTION__ << " " << id << " " << addr_str << " "
<< port << std::endl;
#endif
if(port < 1024)
{
std::cerr << "(EE) attempt to use a port that is reserved to the system: " << port << std::endl;
return false ;
}
// NOTE THIS IS IPV4 FOR NOW.
struct sockaddr_storage addr;
struct sockaddr_in *addrv4p = (struct sockaddr_in *) &addr;
addrv4p->sin_family = AF_INET;
addrv4p->sin_port = htons(port);
int ret = 1;
/********************************** WINDOWS/UNIX SPECIFIC PART *******************/
#ifndef WINDOWS_SYS
if (ret && (0 != inet_aton(addr_str.c_str(), &(addrv4p->sin_addr))))
#else
addrv4p->sin_addr.s_addr = inet_addr(addr_str.c_str());
if (ret)
#endif
/********************************** WINDOWS/UNIX SPECIFIC PART *******************/
{
return mPeerMgr->setExtAddress(id, addr);
}
sockaddr_storage addr;
if (sockaddr_storage_inet_pton(addr, addr_str))
if (sockaddr_storage_setport(addr, port))
return mPeerMgr->setExtAddress(id, addr);
return false;
}

View File

@ -39,7 +39,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();
@ -342,7 +344,7 @@ void p3discovery2::sendOwnContactInfo(const SSLID &sslid)
std::cerr << std::endl;
#endif
peerState detail;
if (mPeerMgr->getOwnNetStatus(detail))
if (mPeerMgr->getOwnNetStatus(detail))
{
RsDiscContactItem *pkt = new RsDiscContactItem();
/* Cyril: we dont send our own IP to an hidden node. It will not use it
@ -461,6 +463,7 @@ void p3discovery2::updatePeerAddressList(const RsDiscContactItem *item)
{
}
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
@ -471,13 +474,13 @@ void p3discovery2::updatePeerAddressList(const RsDiscContactItem *item)
* 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.mExt.extractFromTlv(item->extAddrList);
#ifdef P3DISC_DEBUG
std::cerr << "Setting address list to peer " << item->sslId << ", to be:" << std::endl ;
std::cerr << "Setting address list to peer " << item->sslId
<< ", to be:" << std::endl ;
std::string addrstr;
addrsFromPeer.printAddrs(addrstr);

View File

@ -50,34 +50,37 @@ virtual bool resetAddress(struct sockaddr_in &local) { return false; }
/*******************************************************/
#include "pqi/pqimonitor.h"
#include "util/rsnet.h"
#include "util/stacktrace.h"
#include <iostream>
class rsUdpStack: public UdpStack, public pqiNetListener
{
public:
rsUdpStack(struct sockaddr_in &local)
:UdpStack(local) { return; }
public:
rsUdpStack(struct sockaddr_in &local) : UdpStack(local) {}
rsUdpStack(int testmode, struct sockaddr_in &local)
:UdpStack(testmode, local) { return; }
rsUdpStack(int testmode, struct sockaddr_in &local) :
UdpStack(testmode, local) {}
/* from pqiNetListener */
virtual bool resetListener(const struct sockaddr_storage &local)
/// @see pqiNetListener
virtual bool resetListener(const sockaddr_storage& local)
{
//std::cerr << "rsUdpStack::resetListener(" << sockaddr_storage_tostring(local) << ")";
//std::cerr << std::endl;
sockaddr_storage temp;
sockaddr_storage_copy(local, temp);
if (local.ss_family != AF_INET)
if (!sockaddr_storage_ipv6_to_ipv4(temp))
{
std::cerr << "rsUdpStack::resetListener() NOT IPv4 ERROR";
std::cerr << std::endl;
abort();
std::cerr << __PRETTY_FUNCTION__ << " Got non IPv4 address ERROR"
<< std::endl;
sockaddr_storage_dump(local);
print_stacktrace();
return -EINVAL;
}
struct sockaddr_in *addr = (struct sockaddr_in *) &local;
sockaddr_in *addr = reinterpret_cast<sockaddr_in*>(&temp);
return resetAddress(*addr);
}
};
class rsFixedUdpStack: public UdpStack, public pqiNetListener

View File

@ -88,14 +88,26 @@ std::string rs_inet_ntoa(struct in_addr in);
/***************************/
// sockaddr_storage fns.
// Standard bind, on OSX anyway will not accept a longer socklen for IPv4.
// so hidding details behind function.
int universal_bind(int fd, const struct sockaddr *addr, socklen_t socklen);
int rs_bind(int fd, const sockaddr_storage& addr);
void sockaddr_storage_clear(struct sockaddr_storage &addr);
// mods.
bool sockaddr_storage_zeroip(struct sockaddr_storage &addr);
/**
* @brief Use this function to copy sockaddr_storage.
*
* POSIX does not require that objects of type sockaddr_storage can be copied
* as aggregates thus it is unsafe to aggregate copy ( operator = )
* sockaddr_storage and unexpected behaviors may happens due to padding
* and alignment.
*
* @see https://sourceware.org/bugzilla/show_bug.cgi?id=20111
* @see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71120
*/
bool sockaddr_storage_copy(const sockaddr_storage& src, sockaddr_storage& dst);
bool sockaddr_storage_copyip(struct sockaddr_storage &dst, const struct sockaddr_storage &src);
uint16_t sockaddr_storage_port(const struct sockaddr_storage &addr);
bool sockaddr_storage_setport(struct sockaddr_storage &addr, uint16_t port);
@ -103,10 +115,14 @@ bool sockaddr_storage_setport(struct sockaddr_storage &addr, uint16_t port);
bool sockaddr_storage_setipv4(struct sockaddr_storage &addr, const sockaddr_in *addr_ipv4);
bool sockaddr_storage_setipv6(struct sockaddr_storage &addr, const sockaddr_in6 *addr_ipv6);
bool sockaddr_storage_inet_pton( sockaddr_storage &addr,
const std::string& ipStr );
bool sockaddr_storage_ipv4_aton(struct sockaddr_storage &addr, const char *name);
bool sockaddr_storage_ipv4_setport(struct sockaddr_storage &addr, const uint16_t port);
bool sockaddr_storage_ipv4_to_ipv6(sockaddr_storage &addr);
bool sockaddr_storage_ipv6_to_ipv4(sockaddr_storage &addr);
// comparisons.
bool operator<(const struct sockaddr_storage &a, const struct sockaddr_storage &b);
@ -132,8 +148,12 @@ 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_ipv6_isLinkLocalNet(const sockaddr_storage &addr);
bool sockaddr_storage_isExternalNet(const struct sockaddr_storage &addr);
bool rs_inet_ntop(const sockaddr_storage &addr, std::string &dst);
bool sockaddr_storage_inet_ntop(const sockaddr_storage &addr, std::string &dst);
int rs_setsockopt( int sockfd, int level, int optname,
const uint8_t *optval, uint32_t optlen );
#endif /* RS_UNIVERSAL_NETWORK_HEADER */

View File

@ -26,6 +26,24 @@
#include <sstream>
#include <iomanip>
#include <cstdlib>
#ifdef WINDOWS_SYS
# include <Winsock2.h>
/** Provides Linux like accessor for in6_addr.s6_addr16 for Windows.
* Yet Windows doesn't provide 32 bits accessors so there is no way to use
* in6_addr.s6_addr32 crossplatform.
*/
# define s6_addr16 u.Word
#else
# include <netinet/in.h>
# include <sys/socket.h>
# include <sys/types.h>
# ifdef __APPLE__
/// Provides Linux like accessor for in6_addr.s6_addr16 for Mac.
# define s6_addr16 __u6_addr.__u6_addr16
#endif // __APPLE__
#endif // WINDOWS_SYS
#include "util/rsnet.h"
#include "util/rsstring.h"
@ -90,17 +108,14 @@ bool sockaddr_storage_ipv6_isExternalNet(const struct sockaddr_storage &addr);
/******************************** Socket Fns ***********************************/
// Standard bind, on OSX anyway will not accept a longer socklen for IPv4.
// so hidding details behind function.
int universal_bind(int fd, const struct sockaddr *addr, socklen_t socklen)
int rs_bind(int fd, const sockaddr_storage& addr)
{
#ifdef SS_DEBUG
std::cerr << "universal_bind()";
std::cerr << std::endl;
std::cerr << __PRETTY_FUNCTION__ << std::endl;
#endif
const struct sockaddr_storage *ss_addr = (struct sockaddr_storage *) addr;
socklen_t len = socklen;
switch (ss_addr->ss_family)
socklen_t len = 0;
switch (addr.ss_family)
{
case AF_INET:
len = sizeof(struct sockaddr_in);
@ -110,13 +125,7 @@ int universal_bind(int fd, const struct sockaddr *addr, socklen_t socklen)
break;
}
if (len > socklen)
{
std::cerr << "universal_bind() ERROR len > socklen" << std::endl;
len = socklen;
}
return bind(fd, addr, len);
return bind(fd, reinterpret_cast<const struct sockaddr *>(&addr), len);
}
@ -252,6 +261,58 @@ bool sockaddr_storage_setipv6(struct sockaddr_storage &addr, const sockaddr_in6
return true;
}
#ifdef WINDOWS_SYS
int inet_pton(int af, const char *src, void *dst)
{
sockaddr_storage ss;
int size = sizeof(ss);
char src_copy[INET6_ADDRSTRLEN+1];
ZeroMemory(&ss, sizeof(ss));
/* stupid non-const API */
strncpy (src_copy, src, INET6_ADDRSTRLEN+1);
src_copy[INET6_ADDRSTRLEN] = 0;
if (WSAStringToAddressA(src_copy, af, NULL, (sockaddr *)&ss, &size) == 0)
{
switch(af)
{
case AF_INET:
*(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr;
return 1;
case AF_INET6:
*(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr;
return 1;
}
}
return 0;
}
#endif
bool sockaddr_storage_inet_pton( sockaddr_storage &addr,
const std::string& ipStr )
{
#ifdef SS_DEBUG
std::cerr << __PRETTY_FUNCTION__ << std::endl;
#endif
struct sockaddr_in6 * addrv6p = (struct sockaddr_in6 *) &addr;
struct sockaddr_in * addrv4p = (struct sockaddr_in *) &addr;
if ( 1 == inet_pton(AF_INET6, ipStr.c_str(), &(addrv6p->sin6_addr)) )
{
addr.ss_family = AF_INET6;
return true;
}
else if ( 1 == inet_pton(AF_INET, ipStr.c_str(), &(addrv4p->sin_addr)) )
{
addr.ss_family = AF_INET;
return sockaddr_storage_ipv4_to_ipv6(addr);
}
return false;
}
bool sockaddr_storage_ipv4_aton(struct sockaddr_storage &addr, const char *name)
{
@ -278,21 +339,59 @@ bool sockaddr_storage_ipv4_to_ipv6(sockaddr_storage &addr)
sockaddr_in & addr_ipv4 = (sockaddr_in &) addr;
sockaddr_in6 & addr_ipv6 = (sockaddr_in6 &) addr;
u_int32_t ip = addr_ipv4.sin_addr.s_addr;
u_int16_t port = addr_ipv4.sin_port;
uint32_t ip = addr_ipv4.sin_addr.s_addr;
uint16_t port = addr_ipv4.sin_port;
sockaddr_storage_clear(addr);
addr_ipv6.sin6_family = AF_INET6;
addr_ipv6.sin6_port = port;
addr_ipv6.sin6_addr.s6_addr32[3] = ip;
addr_ipv6.sin6_addr.s6_addr16[5] = (u_int16_t) 0xffff;
addr_ipv6.sin6_addr.s6_addr16[5] = htons(0xffff);
memmove( reinterpret_cast<void*>(&(addr_ipv6.sin6_addr.s6_addr16[6])),
reinterpret_cast<void*>(&ip), 4 );
return true;
}
return false;
}
bool sockaddr_storage_ipv6_to_ipv4(sockaddr_storage &addr)
{
#ifdef SS_DEBUG
std::cerr << __PRETTY_FUNCTION__ << std::endl;
#endif
if ( addr.ss_family == AF_INET ) return true;
if ( addr.ss_family == AF_INET6 )
{
sockaddr_in6 & addr_ipv6 = (sockaddr_in6 &) addr;
bool ipv4m = addr_ipv6.sin6_addr.s6_addr16[5] == htons(0xffff);
for ( int i = 0; ipv4m && i < 5 ; ++i )
ipv4m &= addr_ipv6.sin6_addr.s6_addr16[i] == htons(0x0000);
if(ipv4m)
{
uint32_t ip;
memmove( reinterpret_cast<void*>(&ip),
reinterpret_cast<void*>(&(addr_ipv6.sin6_addr.s6_addr16[6])),
4 );
uint16_t port = addr_ipv6.sin6_port;
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;
return true;
}
}
return false;
}
/******************************** Comparisions **********************************/
bool operator<(const struct sockaddr_storage &a, const struct sockaddr_storage &b)
@ -397,15 +496,20 @@ std::string sockaddr_storage_tostring(const struct sockaddr_storage &addr)
switch(addr.ss_family)
{
case AF_INET:
case AF_INET6:
output += "=";
output += sockaddr_storage_iptostring(addr);
output += ":";
output += sockaddr_storage_porttostring(addr);
break;
default:
break;
case AF_INET:
output += "=";
output += sockaddr_storage_iptostring(addr);
output += ":";
output += sockaddr_storage_porttostring(addr);
break;
case AF_INET6:
output += "=[";
output += sockaddr_storage_iptostring(addr);
output += "]:";
output += sockaddr_storage_porttostring(addr);
break;
default:
break;
}
return output;
}
@ -433,7 +537,7 @@ void sockaddr_storage_dump(const sockaddr_storage & addr, std::string * outputSt
{
const sockaddr_in6 * in6 = (const sockaddr_in6 *) & addr;
std::string addrStr = "INVALID_IPV6";
rs_inet_ntop(addr, addrStr);
sockaddr_storage_inet_ntop(addr, addrStr);
output << "addr.ss_family = AF_INET6";
output << " in6->sin6_addr = ";
output << addrStr;
@ -449,7 +553,8 @@ void sockaddr_storage_dump(const sockaddr_storage & addr, std::string * outputSt
const uint8_t * buf = reinterpret_cast<const uint8_t *>(&addr);
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
/* The unary +buf[i] operation forces a no-op type conversion to an int
* with the correct sign */
}
}
@ -477,6 +582,10 @@ std::string sockaddr_storage_familytostring(const struct sockaddr_storage &addr)
break;
default:
output = "AF_INVALID";
std::cerr << __PRETTY_FUNCTION__ << " Got invalid address!"
<< std::endl;
sockaddr_storage_dump(addr);
print_stacktrace();
break;
}
return output;
@ -487,15 +596,18 @@ std::string sockaddr_storage_iptostring(const struct sockaddr_storage &addr)
std::string output;
switch(addr.ss_family)
{
case AF_INET:
output = sockaddr_storage_ipv4_iptostring(addr);
break;
case AF_INET6:
output = sockaddr_storage_ipv6_iptostring(addr);
break;
default:
output = "INVALID_IP";
break;
case AF_INET:
output = sockaddr_storage_ipv4_iptostring(addr);
break;
case AF_INET6:
output = sockaddr_storage_ipv6_iptostring(addr);
break;
default:
output = "INVALID_IP";
std::cerr << __PRETTY_FUNCTION__ << " Got invalid IP:" << std::endl;
sockaddr_storage_dump(addr);
print_stacktrace();
break;
}
return output;
}
@ -619,9 +731,7 @@ bool sockaddr_storage_isLinkLocalNet(const struct sockaddr_storage &addr)
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;
return sockaddr_storage_ipv6_isLinkLocalNet(addr);
default:
#ifdef SS_DEBUG
std::cerr << __PRETTY_FUNCTION__ <<" INVALID Family:" << std::endl;
@ -633,6 +743,16 @@ bool sockaddr_storage_isLinkLocalNet(const struct sockaddr_storage &addr)
return false;
}
bool sockaddr_storage_ipv6_isLinkLocalNet(const sockaddr_storage &addr)
{
if(addr.ss_family != AF_INET6) return false;
const sockaddr_in6 * addr6 = (const sockaddr_in6 *) &addr;
uint16_t mask = htons(0xffc0);
uint16_t llPrefix = htons(0xfe80);
return ((addr6->sin6_addr.s6_addr16[0] & mask ) == llPrefix);
}
bool sockaddr_storage_isExternalNet(const struct sockaddr_storage &addr)
{
@ -695,6 +815,51 @@ const struct sockaddr_in6 *to_const_ipv6_ptr(const struct sockaddr_storage &addr
/******************************** Set / Clear ***********************************/
bool sockaddr_storage_copy(const sockaddr_storage& src, sockaddr_storage& dst)
{
if(&src == &dst) return true;
switch(src.ss_family)
{
case AF_INET:
{
sockaddr_storage_clear(dst);
const sockaddr_in& ins(reinterpret_cast<const sockaddr_in&>(src));
sockaddr_in& ind(reinterpret_cast<sockaddr_in&>(dst));
ind.sin_family = AF_INET;
ind.sin_addr.s_addr = ins.sin_addr.s_addr;
ind.sin_port = ins.sin_port;
return true;
}
case AF_INET6:
{
sockaddr_storage_clear(dst);
const sockaddr_in6& ins6(reinterpret_cast<const sockaddr_in6&>(src));
sockaddr_in6& ind6(reinterpret_cast<sockaddr_in6&>(dst));
ind6.sin6_family = AF_INET6;
for(int i=0; i<8; ++i)
ind6.sin6_addr.s6_addr16[i] = ins6.sin6_addr.s6_addr16[i];
ind6.sin6_flowinfo = ins6.sin6_flowinfo;
ind6.sin6_port = ins6.sin6_port;
ind6.sin6_scope_id = ins6.sin6_scope_id;
return true;
}
default:
#ifdef SS_DEBUG
std::cerr << __PRETTY_FUNCTION__ << " Attempt to copy unknown family! "
<< src.ss_family << " defaulting to memmove!" << std::endl;
sockaddr_storage_dump(src);
print_stacktrace();
#endif // SS_DEBUG
memmove(&dst, &src, sizeof(sockaddr_storage));
return true;
}
}
bool sockaddr_storage_ipv4_zeroip(struct sockaddr_storage &addr)
{
#ifdef SS_DEBUG
@ -917,7 +1082,7 @@ std::string sockaddr_storage_ipv4_iptostring(const struct sockaddr_storage &addr
std::string sockaddr_storage_ipv6_iptostring(const struct sockaddr_storage & addr)
{
std::string addrStr;
rs_inet_ntop(addr, addrStr);
sockaddr_storage_inet_ntop(addr, addrStr);
return addrStr;
}
@ -1006,62 +1171,58 @@ bool sockaddr_storage_ipv4_isExternalNet(const struct sockaddr_storage &addr)
}
bool sockaddr_storage_ipv6_isnull(const struct sockaddr_storage &/*addr*/)
bool sockaddr_storage_ipv6_isnull(const struct sockaddr_storage& addr)
{
#ifdef SS_DEBUG
std::cerr << "sockaddr_storage_ipv6_isnull() TODO";
std::cerr << std::endl;
#endif
const sockaddr_in6& addr6 = reinterpret_cast<const sockaddr_in6&>(addr);
return false;
uint16_t nZero = htons(0); // anyway 0 should be the same in host and net
bool isZero = (addr6.sin6_addr.s6_addr16[7] == nZero);
for (int i=0; isZero && i<7; ++i)
isZero &= (addr6.sin6_addr.s6_addr16[i] == nZero);
return nZero;
}
bool sockaddr_storage_ipv6_isValidNet(const struct sockaddr_storage &/*addr*/)
bool sockaddr_storage_ipv6_isValidNet(const struct sockaddr_storage& addr)
{
#ifdef SS_DEBUG
std::cerr << "sockaddr_storage_ipv6_isValidNet() TODO";
std::cerr << std::endl;
#endif
return false;
return !sockaddr_storage_ipv6_isnull(addr);
}
bool sockaddr_storage_ipv6_isLoopbackNet(const struct sockaddr_storage &/*addr*/)
bool sockaddr_storage_ipv6_isLoopbackNet(const struct sockaddr_storage& addr)
{
const sockaddr_in6& addr6 = reinterpret_cast<const sockaddr_in6&>(addr);
bool isLoopBack = (addr6.sin6_addr.s6_addr16[7] == htons(0x0001));
uint16_t nZero = htons(0); // anyway 0 should be the same in host and net
for (int i=0; isLoopBack && i<7; ++i)
isLoopBack &= (addr6.sin6_addr.s6_addr16[i] == nZero);
#ifdef SS_DEBUG
std::cerr << "sockaddr_storage_ipv6_isLoopbackNet() TODO";
std::cerr << std::endl;
std::cerr << __PRETTY_FUNCTION__ << " " << sockaddr_storage_tostring(addr)
<< " " << isLoopBack << std::endl;
#endif
return false;
return isLoopBack;
}
bool sockaddr_storage_ipv6_isPrivateNet(const struct sockaddr_storage &/*addr*/)
{
#ifdef SS_DEBUG
std::cerr << "sockaddr_storage_ipv6_isPrivateNet() TODO";
std::cerr << std::endl;
#endif
/* It is unlikely that we end up connecting to an IPv6 address behind NAT
* W.R.T. RS it is probably better to consider all IPv6 as internal/local
* addresses as direct connection should be always possible. */
return false;
return true;
}
bool sockaddr_storage_ipv6_isExternalNet(const struct sockaddr_storage &/*addr*/)
{
#ifdef SS_DEBUG
std::cerr << "sockaddr_storage_ipv6_isExternalNet() TODO";
std::cerr << std::endl;
#endif
/* It is unlikely that we end up connecting to an IPv6 address behind NAT
* W.R.T. RS it is probably better to consider all IPv6 as internal/local
* addresses as direct connection should be always possible. */
return false;
}
#ifdef WINDOWS_SYS
#include <cstdlib>
#include <Winsock2.h>
#endif
bool rs_inet_ntop (const sockaddr_storage &addr, std::string &dst)
bool sockaddr_storage_inet_ntop (const sockaddr_storage &addr, std::string &dst)
{
bool success = false;
char ipStr[255];
@ -1098,3 +1259,15 @@ bool rs_inet_ntop (const sockaddr_storage &addr, std::string &dst)
dst = ipStr;
return success;
}
int rs_setsockopt( int sockfd, int level, int optname,
const uint8_t *optval, uint32_t optlen )
{
#ifdef WINDOWS_SYS
return setsockopt( sockfd, level, optname,
reinterpret_cast<const char*>(optval), optlen );
#else
return setsockopt( sockfd, level, optname,
reinterpret_cast<const void*>(optval), optlen );
#endif // WINDOWS_SYS
}

View File

@ -169,11 +169,14 @@ void RsTickingThread::fullstop()
void RsThread::start(const std::string &threadName)
{
if(isRunning())
{
std::cerr << "(EE) RsThread \"" << threadName << "\" is already running. Will not start twice!" << std::endl;
return ;
}
if(isRunning())
{
std::cerr << "(EE) RsThread \"" << threadName
<< "\" is already running. Will not start twice!"
<< std::endl;
print_stacktrace();
return;
}
pthread_t tid;
void *data = (void *)this ;