From b3c7d195c874d761a62e02cd051c08f30300fa31 Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Thu, 22 Feb 2018 12:18:51 +0100 Subject: [PATCH] Port pqissl to dual stack IPv6+IPv4 Changed unix_connect signature to be more comfortable for dual stack usage Remove dead code in pqissl::pqissl(...) Adapt p3I2pBob::connectI2P() to new unix_connect Adapt extaddrfinder to new unix_connect Add sockaddr_storage_ipv4_to_ipv6 to convert from flat IPv4 to IPv4 mapped as IPv6 --- libretroshare/src/pqi/p3linkmgr.cc | 3 +- libretroshare/src/pqi/pqinetwork.cc | 34 +-------- libretroshare/src/pqi/pqinetwork.h | 2 +- libretroshare/src/pqi/pqissl.cc | 74 ++++++++----------- libretroshare/src/pqi/pqissl.h | 3 +- .../src/services/autoproxy/p3i2pbob.cc | 4 +- libretroshare/src/util/extaddrfinder.cc | 5 +- libretroshare/src/util/rsnet.h | 1 + libretroshare/src/util/rsnet_ss.cc | 27 +++++++ 9 files changed, 72 insertions(+), 81 deletions(-) diff --git a/libretroshare/src/pqi/p3linkmgr.cc b/libretroshare/src/pqi/p3linkmgr.cc index c84b8ea4f..d3e2b50d0 100644 --- a/libretroshare/src/pqi/p3linkmgr.cc +++ b/libretroshare/src/pqi/p3linkmgr.cc @@ -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 * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public diff --git a/libretroshare/src/pqi/pqinetwork.cc b/libretroshare/src/pqi/pqinetwork.cc index c302123a4..058e1cd07 100644 --- a/libretroshare/src/pqi/pqinetwork.cc +++ b/libretroshare/src/pqi/pqinetwork.cc @@ -438,43 +438,17 @@ int unix_fcntl_nonblock(int fd) } -int unix_connect(int fd, const struct sockaddr *serv_addr, socklen_t socklen) +int unix_connect(int fd, const sockaddr_storage &serv_addr) { #ifdef NET_DEBUG - std::cerr << "unix_connect()"; - std::cerr << std::endl; + std::cerr << __PRETTY_FUNCTION__ << std::endl; #endif - const struct sockaddr_storage *ss_addr = (struct sockaddr_storage *) serv_addr; - socklen_t len = socklen; - - switch (ss_addr->ss_family) - { - case AF_INET: - len = sizeof(struct sockaddr_in); - break; - case AF_INET6: - len = sizeof(struct sockaddr_in6); - break; - } - - if (len > socklen) - { - std::cerr << "unix_connect() ERROR len > socklen"; - std::cerr << std::endl; - - len = socklen; - //return EINVAL; - } - - int ret = connect(fd, serv_addr, len); + int ret = connect( fd, (const struct sockaddr *) &serv_addr, + sizeof(struct sockaddr_in6) ); /******************* WINDOWS SPECIFIC PART ******************/ #ifdef WINDOWS_SYS // WINDOWS - -#ifdef NET_DEBUG - std::cerr << "unix_connect()" << std::endl; -#endif if (ret != 0) { errno = WinToUnixError(WSAGetLastError()); diff --git a/libretroshare/src/pqi/pqinetwork.h b/libretroshare/src/pqi/pqinetwork.h index 21d8ee81c..e974f68cf 100644 --- a/libretroshare/src/pqi/pqinetwork.h +++ b/libretroshare/src/pqi/pqinetwork.h @@ -103,7 +103,7 @@ bool getLocalAddresses(std::vector & addrs); int unix_close(int sockfd); int unix_socket(int domain, int type, int protocol); int unix_fcntl_nonblock(int sockfd); -int unix_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen); +int unix_connect(int sockfd, const sockaddr_storage& serv_addr); int unix_getsockopt_error(int sockfd, int *err); #ifdef WINDOWS_SYS // WINDOWS diff --git a/libretroshare/src/pqi/pqissl.cc b/libretroshare/src/pqi/pqissl.cc index 898080262..74bf6f8d2 100644 --- a/libretroshare/src/pqi/pqissl.cc +++ b/libretroshare/src/pqi/pqissl.cc @@ -4,6 +4,7 @@ * 3P/PQI network interface for RetroShare. * * Copyright 2004-2006 by Robert Fernie. + * Copyright (C) 2015-2018 Gioacchino Mazzurco * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -96,44 +97,14 @@ static const int PQISSL_SSL_CONNECT_TIMEOUT = 30; * */ -pqissl::pqissl(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm) - :NetBinInterface(parent, parent->PeerId()), - mLinkMgr(lm), pqil(l), - mSslMtx("pqissl"), - active(false), certvalid(false), waiting(WAITING_NOT), - sslmode(PQISSL_ACTIVE), ssl_connection(NULL), sockfd(-1), - readpkt(NULL), pktlen(0), total_len(0), - attempt_ts(0), - n_read_zero(0), mReadZeroTS(0), ssl_connect_timeout(0), - mConnectDelay(0), mConnectTS(0), - mConnectTimeout(0), mTimeoutTS(0) -{ - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - - /* set address to zero */ - sockaddr_storage_clear(remote_addr); - -#ifdef PQISSL_LOG_DEBUG - rslog(RSL_DEBUG_BASIC, pqisslzone, "pqissl for PeerId: " + PeerId()); -#endif - -#if 0 - if (!(AuthSSL::getAuthSSL()->isAuthenticated(PeerId()))) - { - rslog(RSL_ALERT, pqisslzone, - "pqissl::Warning Certificate Not Approved!"); - - rslog(RSL_ALERT, pqisslzone, - "\t pqissl will not initialise...."); - - } -#else - rslog(RSL_DEBUG_BASIC, pqisslzone, - "pqissl::Warning SSL Certificate Approval Not CHECKED??"); -#endif - - return; -} +pqissl::pqissl(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm) : + NetBinInterface(parent, parent->PeerId()), + mLinkMgr(lm), pqil(l), mSslMtx("pqissl"), active(false), certvalid(false), + waiting(WAITING_NOT), sslmode(PQISSL_ACTIVE), ssl_connection(NULL), + sockfd(-1), readpkt(NULL), pktlen(0), total_len(0), attempt_ts(0), + n_read_zero(0), mReadZeroTS(0), ssl_connect_timeout(0), mConnectDelay(0), + mConnectTS(0), mConnectTimeout(0), mTimeoutTS(0) +{ sockaddr_storage_clear(remote_addr); } pqissl::~pqissl() { @@ -151,11 +122,8 @@ pqissl::pqissl(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm) int pqissl::connect(const struct sockaddr_storage &raddr) { - RsStackMutex stack(mSslMtx); /**** LOCKED MUTEX ****/ - - // reset failures + RS_STACK_MUTEX(mSslMtx); remote_addr = raddr; - return ConnectAttempt(); } @@ -613,7 +581,7 @@ int pqissl::Delay_Connection() } -int pqissl::Initiate_Connection() +int pqissl::Initiate_Connection() { int err; struct sockaddr_storage addr = remote_addr; @@ -636,7 +604,7 @@ int pqissl::Initiate_Connection() #endif // open socket connection to addr. - int osock = unix_socket(PF_INET, SOCK_STREAM, 0); + int osock = unix_socket(PF_INET6, SOCK_STREAM, 0); #ifdef PQISSL_LOG_DEBUG { @@ -736,10 +704,26 @@ int pqissl::Initiate_Connection() #endif #endif // WINDOWS_SYS + /* Systems that supports dual stack sockets defines IPV6_V6ONLY and some set + * it to 1 by default. This enable dual stack socket on such systems. + * Systems which don't support dual stack (only Windows older then XP SP3) + * will support IPv6 only and not IPv4 */ +#ifdef IPV6_V6ONLY + int no = 0; + err = setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&no, sizeof(no)); +#ifdef PQISSL_DEBUG + if (err) std::cerr << __PRETTY_FUNCTION__ + << " Error setting IPv6 socket dual stack" << std::endl; + else std::cerr << __PRETTY_FUNCTION__ + << " Setting IPv6 socket dual stack" << std::endl; +#endif // PQISSL_DEBUG +#endif // IPV6_V6ONLY + mTimeoutTS = time(NULL) + mConnectTimeout; //std::cerr << "Setting Connect Timeout " << mConnectTimeout << " Seconds into Future " << std::endl; - if (0 != (err = unix_connect(osock, (struct sockaddr *) &addr, sizeof(addr)))) + sockaddr_storage_ipv4_to_ipv6(addr); + if (0 != (err = unix_connect(osock, addr))) { std::string out; rs_sprintf(out, "pqissl::Initiate_Connection() connect returns:%d -> errno: %d error: %s\n", err, errno, socket_errorType(errno).c_str()); diff --git a/libretroshare/src/pqi/pqissl.h b/libretroshare/src/pqi/pqissl.h index b4cd267d6..5748f5a9c 100644 --- a/libretroshare/src/pqi/pqissl.h +++ b/libretroshare/src/pqi/pqissl.h @@ -4,6 +4,7 @@ * 3P/PQI network interface for RetroShare. * * Copyright 2004-2006 by Robert Fernie. + * Copyright (C) 2015-2018 Gioacchino Mazzurco * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -114,7 +115,7 @@ virtual bool cansend(uint32_t usec); virtual int close(); /* BinInterface version of reset() */ virtual RsFileHash gethash(); /* not used here */ -virtual bool bandwidthLimited() { return true ; } // replace by !sameLAN to avoid bandwidth limiting on LAN +virtual bool bandwidthLimited() { return true ; } public: diff --git a/libretroshare/src/services/autoproxy/p3i2pbob.cc b/libretroshare/src/services/autoproxy/p3i2pbob.cc index 917b8a8a7..36e5604c7 100644 --- a/libretroshare/src/services/autoproxy/p3i2pbob.cc +++ b/libretroshare/src/services/autoproxy/p3i2pbob.cc @@ -890,7 +890,7 @@ bool p3I2pBob::connectI2P() } // create socket - mSocket = unix_socket(AF_INET, SOCK_STREAM, 0); + mSocket = unix_socket(PF_INET, SOCK_STREAM, 0); if (mSocket < 0) { rslog(RsLog::Warning, &i2pBobLogInfo, "connectI2P_locked Failed to open socket! Socket Error: " + socket_errorType(errno)); @@ -898,7 +898,7 @@ bool p3I2pBob::connectI2P() } // connect - int err = unix_connect(mSocket, (struct sockaddr *)&mI2PProxyAddr, sizeof(mI2PProxyAddr)); + int err = unix_connect(mSocket, mI2PProxyAddr); if (err != 0) { rslog(RsLog::Warning, &i2pBobLogInfo, "connectI2P_locked Failed to connect to BOB! Socket Error: " + socket_errorType(errno)); return false; diff --git a/libretroshare/src/util/extaddrfinder.cc b/libretroshare/src/util/extaddrfinder.cc index e01e37211..308a8ea48 100644 --- a/libretroshare/src/util/extaddrfinder.cc +++ b/libretroshare/src/util/extaddrfinder.cc @@ -94,7 +94,10 @@ static void getPage(const std::string& server_name,std::string& page) #endif std::cerr << "ExtAddrFinder: resolved hostname " << server_name << " to " << rs_inet_ntoa(in) << std::endl; - if(unix_connect(sockfd,(struct sockaddr *)&serveur, sizeof(serveur)) == -1) + sockaddr_storage server; + sockaddr_storage_setipv4(server, &serveur); + sockaddr_storage_setport(server, 80); + if(unix_connect(sockfd, server) == -1) { std::cerr << "ExtAddrFinder: Connection error to " << server_name << std::endl ; unix_close(sockfd); diff --git a/libretroshare/src/util/rsnet.h b/libretroshare/src/util/rsnet.h index ffd34ffb7..903ee0a65 100644 --- a/libretroshare/src/util/rsnet.h +++ b/libretroshare/src/util/rsnet.h @@ -106,6 +106,7 @@ bool sockaddr_storage_setipv6(struct sockaddr_storage &addr, const sockaddr_in6 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); // comparisons. bool operator<(const struct sockaddr_storage &a, const struct sockaddr_storage &b); diff --git a/libretroshare/src/util/rsnet_ss.cc b/libretroshare/src/util/rsnet_ss.cc index 1d94aa882..ad4db25ac 100644 --- a/libretroshare/src/util/rsnet_ss.cc +++ b/libretroshare/src/util/rsnet_ss.cc @@ -265,6 +265,33 @@ bool sockaddr_storage_ipv4_aton(struct sockaddr_storage &addr, const char *name) return (1 == inet_aton(name, &(ipv4_ptr->sin_addr))); } +bool sockaddr_storage_ipv4_to_ipv6(sockaddr_storage &addr) +{ +#ifdef SS_DEBUG + std::cerr << __PRETTY_FUNCTION__ << std::endl; +#endif + + if ( addr.ss_family == AF_INET6 ) return true; + + if ( addr.ss_family == AF_INET ) + { + 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; + + 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; + + return true; + } + + return false; +} /******************************** Comparisions **********************************/