Network.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /*
  2. This file is part of cpp-ethereum.
  3. cpp-ethereum is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. cpp-ethereum is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. /** @file Network.cpp
  15. * @author Alex Leverington <nessence@gmail.com>
  16. * @author Gav Wood <i@gavwood.com>
  17. * @author Eric Lombrozo <elombrozo@gmail.com> (Windows version of getInterfaceAddresses())
  18. * @date 2014
  19. */
  20. #include <sys/types.h>
  21. #ifndef _WIN32
  22. #include <ifaddrs.h>
  23. #endif
  24. #include <boost/algorithm/string.hpp>
  25. #include <boost/algorithm/string/split.hpp>
  26. #include <libdevcore/Common.h>
  27. #include <libdevcore/Assertions.h>
  28. #include <libdevcore/CommonIO.h>
  29. #include <libdevcore/Exceptions.h>
  30. #include "Common.h"
  31. #include "UPnP.h"
  32. #include "Network.h"
  33. using namespace std;
  34. using namespace dev;
  35. using namespace dev::p2p;
  36. std::set<bi::address> Network::getInterfaceAddresses()
  37. {
  38. std::set<bi::address> addresses;
  39. #if defined(_WIN32)
  40. WSAData wsaData;
  41. if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
  42. BOOST_THROW_EXCEPTION(NoNetworking());
  43. char ac[80];
  44. if (gethostname(ac, sizeof(ac)) == SOCKET_ERROR)
  45. {
  46. clog(NetWarn) << "Error " << WSAGetLastError() << " when getting local host name.";
  47. WSACleanup();
  48. BOOST_THROW_EXCEPTION(NoNetworking());
  49. }
  50. struct hostent* phe = gethostbyname(ac);
  51. if (phe == 0)
  52. {
  53. clog(NetWarn) << "Bad host lookup.";
  54. WSACleanup();
  55. BOOST_THROW_EXCEPTION(NoNetworking());
  56. }
  57. for (int i = 0; phe->h_addr_list[i] != 0; ++i)
  58. {
  59. struct in_addr addr;
  60. memcpy(&addr, phe->h_addr_list[i], sizeof(struct in_addr));
  61. char *addrStr = inet_ntoa(addr);
  62. bi::address address(bi::address::from_string(addrStr));
  63. if (!isLocalHostAddress(address))
  64. addresses.insert(address.to_v4());
  65. }
  66. WSACleanup();
  67. #else
  68. ifaddrs* ifaddr;
  69. if (getifaddrs(&ifaddr) == -1)
  70. BOOST_THROW_EXCEPTION(NoNetworking());
  71. for (auto ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
  72. {
  73. if (!ifa->ifa_addr || string(ifa->ifa_name) == "lo0" || !(ifa->ifa_flags & IFF_UP))
  74. continue;
  75. if (ifa->ifa_addr->sa_family == AF_INET)
  76. {
  77. in_addr addr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
  78. boost::asio::ip::address_v4 address(boost::asio::detail::socket_ops::network_to_host_long(addr.s_addr));
  79. if (!isLocalHostAddress(address))
  80. addresses.insert(address);
  81. }
  82. else if (ifa->ifa_addr->sa_family == AF_INET6)
  83. {
  84. sockaddr_in6* sockaddr = ((struct sockaddr_in6 *)ifa->ifa_addr);
  85. in6_addr addr = sockaddr->sin6_addr;
  86. boost::asio::ip::address_v6::bytes_type bytes;
  87. memcpy(&bytes[0], addr.s6_addr, 16);
  88. boost::asio::ip::address_v6 address(bytes, sockaddr->sin6_scope_id);
  89. if (!isLocalHostAddress(address))
  90. addresses.insert(address);
  91. }
  92. }
  93. if (ifaddr!=NULL)
  94. freeifaddrs(ifaddr);
  95. #endif
  96. return addresses;
  97. }
  98. int Network::tcp4Listen(bi::tcp::acceptor& _acceptor, NetworkPreferences const& _netPrefs)
  99. {
  100. // Due to the complexities of NAT and network environments (multiple NICs, tunnels, etc)
  101. // and security concerns automation is the enemy of network configuration.
  102. // If a preference cannot be accommodate the network must fail to start.
  103. //
  104. // Preferred IP: Attempt if set, else, try 0.0.0.0 (all interfaces)
  105. // Preferred Port: Attempt if set, else, try c_defaultListenPort or 0 (random)
  106. // TODO: throw instead of returning -1 and rename NetworkPreferences to NetworkConfig
  107. bi::address listenIP;
  108. try
  109. {
  110. listenIP = _netPrefs.listenIPAddress.empty() ? bi::address_v4() : bi::address::from_string(_netPrefs.listenIPAddress);
  111. }
  112. catch (...)
  113. {
  114. cwarn << "Couldn't start accepting connections on host. Failed to accept socket on " << listenIP << ":" << _netPrefs.listenPort << ".\n" << boost::current_exception_diagnostic_information();
  115. return -1;
  116. }
  117. bool requirePort = (bool)_netPrefs.listenPort;
  118. for (unsigned i = 0; i < 2; ++i)
  119. {
  120. bi::tcp::endpoint endpoint(listenIP, requirePort ? _netPrefs.listenPort : (i ? 0 : c_defaultListenPort));
  121. try
  122. {
  123. #if defined(_WIN32)
  124. bool reuse = false;
  125. #else
  126. bool reuse = true;
  127. #endif
  128. _acceptor.open(endpoint.protocol());
  129. _acceptor.set_option(ba::socket_base::reuse_address(reuse));
  130. _acceptor.bind(endpoint);
  131. _acceptor.listen();
  132. return _acceptor.local_endpoint().port();
  133. }
  134. catch (...)
  135. {
  136. // bail if this is first attempt && port was specificed, or second attempt failed (random port)
  137. if (i || requirePort)
  138. {
  139. // both attempts failed
  140. cwarn << "Couldn't start accepting connections on host. Failed to accept socket on " << listenIP << ":" << _netPrefs.listenPort << ".\n" << boost::current_exception_diagnostic_information();
  141. _acceptor.close();
  142. return -1;
  143. }
  144. _acceptor.close();
  145. continue;
  146. }
  147. }
  148. return -1;
  149. }
  150. bi::tcp::endpoint Network::traverseNAT(std::set<bi::address> const& _ifAddresses, unsigned short _listenPort, bi::address& o_upnpInterfaceAddr)
  151. {
  152. asserts(_listenPort != 0);
  153. unique_ptr<UPnP> upnp;
  154. try
  155. {
  156. upnp.reset(new UPnP);
  157. }
  158. // let m_upnp continue as null - we handle it properly.
  159. catch (...) {}
  160. bi::tcp::endpoint upnpEP;
  161. if (upnp && upnp->isValid())
  162. {
  163. bi::address pAddr;
  164. int extPort = 0;
  165. for (auto const& addr: _ifAddresses)
  166. if (addr.is_v4() && isPrivateAddress(addr) && (extPort = upnp->addRedirect(addr.to_string().c_str(), _listenPort)))
  167. {
  168. pAddr = addr;
  169. break;
  170. }
  171. auto eIP = upnp->externalIP();
  172. bi::address eIPAddr(bi::address::from_string(eIP));
  173. if (extPort && eIP != string("0.0.0.0") && !isPrivateAddress(eIPAddr))
  174. {
  175. clog(NetNote) << "Punched through NAT and mapped local port" << _listenPort << "onto external port" << extPort << ".";
  176. clog(NetNote) << "External addr:" << eIP;
  177. o_upnpInterfaceAddr = pAddr;
  178. upnpEP = bi::tcp::endpoint(eIPAddr, (unsigned short)extPort);
  179. }
  180. else
  181. clog(NetWarn) << "Couldn't punch through NAT (or no NAT in place).";
  182. }
  183. return upnpEP;
  184. }
  185. bi::tcp::endpoint Network::resolveHost(string const& _addr)
  186. {
  187. static boost::asio::io_service s_resolverIoService;
  188. vector<string> split;
  189. boost::split(split, _addr, boost::is_any_of(":"));
  190. unsigned port = dev::p2p::c_defaultIPPort;
  191. try
  192. {
  193. if (split.size() > 1)
  194. port = static_cast<unsigned>(stoi(split.at(1)));
  195. }
  196. catch(...) {}
  197. boost::system::error_code ec;
  198. bi::address address = bi::address::from_string(split[0], ec);
  199. bi::tcp::endpoint ep(bi::address(), port);
  200. if (!ec)
  201. ep.address(address);
  202. else
  203. {
  204. boost::system::error_code ec;
  205. // resolve returns an iterator (host can resolve to multiple addresses)
  206. bi::tcp::resolver r(s_resolverIoService);
  207. auto it = r.resolve({bi::tcp::v4(), split[0], toString(port)}, ec);
  208. if (ec)
  209. {
  210. clog(NetWarn) << "Error resolving host address..." << LogTag::Url << _addr << ":" << LogTag::Error << ec.message();
  211. return bi::tcp::endpoint();
  212. }
  213. else
  214. ep = *it;
  215. }
  216. return ep;
  217. }