From 529f3931dde86fb06a2e786dadfb5ea084783847 Mon Sep 17 00:00:00 2001 From: Annanay Date: Mon, 29 Jan 2018 01:37:08 +0530 Subject: [PATCH 01/17] Add basic NATPMP support, get gateway by file parsing, getpublicaddress, map public-private port --- src/getgateway.c | 570 ++++++++++++++++++++++++++++++++++++++++++ src/getgateway.h | 47 ++++ src/natpmp.c | 354 ++++++++++++++++++++++++++ src/natpmp.h | 182 ++++++++++++++ src/net.cpp | 187 +++++++------- src/wingettimeofday.c | 60 +++++ src/wingettimeofday.h | 36 +++ 7 files changed, 1348 insertions(+), 88 deletions(-) create mode 100644 src/getgateway.c create mode 100644 src/getgateway.h create mode 100644 src/natpmp.c create mode 100644 src/natpmp.h create mode 100644 src/wingettimeofday.c create mode 100644 src/wingettimeofday.h diff --git a/src/getgateway.c b/src/getgateway.c new file mode 100644 index 0000000000000..27ab473a6f048 --- /dev/null +++ b/src/getgateway.c @@ -0,0 +1,570 @@ +/* $Id: getgateway.c,v 1.24 2014/03/31 12:41:35 nanard Exp $ */ +/* libnatpmp +Copyright (c) 2007-2014, Thomas BERNARD +All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include +#ifndef WIN32 +#include +#endif +#if !defined(_MSC_VER) +#include +#endif +/* There is no portable method to get the default route gateway. + * So below are four (or five ?) differents functions implementing this. + * Parsing /proc/net/route is for linux. + * sysctl is the way to access such informations on BSD systems. + * Many systems should provide route information through raw PF_ROUTE + * sockets. + * In MS Windows, default gateway is found by looking into the registry + * or by using GetBestRoute(). */ +#ifdef __linux__ +#define USE_PROC_NET_ROUTE +#undef USE_SOCKET_ROUTE +#undef USE_SYSCTL_NET_ROUTE +#endif + +#if defined(__OpenBSD__) || defined(__FreeBSD__) +#undef USE_PROC_NET_ROUTE +#define USE_SOCKET_ROUTE +#undef USE_SYSCTL_NET_ROUTE +#endif + +#ifdef __APPLE__ +#undef USE_PROC_NET_ROUTE +#undef USE_SOCKET_ROUTE +#define USE_SYSCTL_NET_ROUTE +#endif + +#if (defined(sun) && defined(__SVR4)) +#undef USE_PROC_NET_ROUTE +#define USE_SOCKET_ROUTE +#undef USE_SYSCTL_NET_ROUTE +#endif + +#ifdef WIN32 +#undef USE_PROC_NET_ROUTE +#undef USE_SOCKET_ROUTE +#undef USE_SYSCTL_NET_ROUTE +//#define USE_WIN32_CODE +#define USE_WIN32_CODE_2 +#endif + +#ifdef __CYGWIN__ +#undef USE_PROC_NET_ROUTE +#undef USE_SOCKET_ROUTE +#undef USE_SYSCTL_NET_ROUTE +#define USE_WIN32_CODE +#include +#include +#include +#include +#endif + +#ifdef __HAIKU__ +#include +#include +#include +#include +#define USE_HAIKU_CODE +#endif + +#ifdef USE_SYSCTL_NET_ROUTE +#include +#include +#include +#include +#endif +#ifdef USE_SOCKET_ROUTE +#include +#include +#include +#include +#include +#endif + +#ifdef USE_WIN32_CODE +#include +#include +#define MAX_KEY_LENGTH 255 +#define MAX_VALUE_LENGTH 16383 +#endif + +#ifdef USE_WIN32_CODE_2 +#include +#include +#include +#endif + +#include + +#ifndef _WIN32 +#define SUCCESS (0) +#define FAILED (-1) +#endif + +#if defined(USE_PROC_NET_ROUTE) + +/* + parse /proc/net/route which is as follow : + +Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT +wlan0 0001A8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0 +eth0 0000FEA9 00000000 0001 0 0 0 0000FFFF 0 0 0 +wlan0 00000000 0101A8C0 0003 0 0 0 00000000 0 0 0 +eth0 00000000 00000000 0001 0 0 1000 00000000 0 0 0 + + One header line, and then one line by route by route table entry. +*/ +int getdefaultgateway(in_addr_t * addr) +{ + unsigned long d, g; + char buf[256]; + int line = 0; + FILE * f; + char * p; + f = fopen("/proc/net/route", "r"); + if(!f) + return FAILED; + while(fgets(buf, sizeof(buf), f)) { + if(line > 0) { /* skip the first line */ + p = buf; + /* skip the interface name */ + while(*p && !isspace(*p)) + p++; + while(*p && isspace(*p)) + p++; + if(sscanf(p, "%lx%lx", &d, &g)==2) { + if(d == 0 && g != 0) { /* default */ + *addr = g; + fclose(f); + return SUCCESS; + } + } + } + line++; + } + /* default route not found ! */ + if(f) + fclose(f); + return FAILED; +} + +#elif defined(USE_SYSCTL_NET_ROUTE) + +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) + +int getdefaultgateway(in_addr_t * addr) +{ +#if 0 + /* net.route.0.inet.dump.0.0 ? */ + int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET, + NET_RT_DUMP, 0, 0/*tableid*/}; +#endif + /* net.route.0.inet.flags.gateway */ + int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET, + NET_RT_FLAGS, RTF_GATEWAY}; + size_t l; + char * buf, * p; + struct rt_msghdr * rt; + struct sockaddr * sa; + struct sockaddr * sa_tab[RTAX_MAX]; + int i; + int r = FAILED; + if(sysctl(mib, sizeof(mib)/sizeof(int), 0, &l, 0, 0) < 0) { + return FAILED; + } + if(l>0) { + buf = malloc(l); + if(sysctl(mib, sizeof(mib)/sizeof(int), buf, &l, 0, 0) < 0) { + free(buf); + return FAILED; + } + for(p=buf; prtm_msglen) { + rt = (struct rt_msghdr *)p; + sa = (struct sockaddr *)(rt + 1); + for(i=0; irtm_addrs & (1 << i)) { + sa_tab[i] = sa; + sa = (struct sockaddr *)((char *)sa + ROUNDUP(sa->sa_len)); + } else { + sa_tab[i] = NULL; + } + } + if( ((rt->rtm_addrs & (RTA_DST|RTA_GATEWAY)) == (RTA_DST|RTA_GATEWAY)) + && sa_tab[RTAX_DST]->sa_family == AF_INET + && sa_tab[RTAX_GATEWAY]->sa_family == AF_INET) { + if(((struct sockaddr_in *)sa_tab[RTAX_DST])->sin_addr.s_addr == 0) { + *addr = ((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr; + r = SUCCESS; + } + } + } + free(buf); + } + return r; +} + +#elif defined(USE_SOCKET_ROUTE) + +/* Thanks to Darren Kenny for this code */ +#define NEXTADDR(w, u) \ + if (rtm_addrs & (w)) {\ + l = sizeof(struct sockaddr); memmove(cp, &(u), l); cp += l;\ + } + +#define rtm m_rtmsg.m_rtm + +struct { + struct rt_msghdr m_rtm; + char m_space[512]; +} m_rtmsg; + +int getdefaultgateway(in_addr_t *addr) +{ + int s, seq, l, rtm_addrs, i; + pid_t pid; + struct sockaddr so_dst, so_mask; + char *cp = m_rtmsg.m_space; + struct sockaddr *gate = NULL, *sa; + struct rt_msghdr *msg_hdr; + + pid = getpid(); + seq = 0; + rtm_addrs = RTA_DST | RTA_NETMASK; + + memset(&so_dst, 0, sizeof(so_dst)); + memset(&so_mask, 0, sizeof(so_mask)); + memset(&rtm, 0, sizeof(struct rt_msghdr)); + + rtm.rtm_type = RTM_GET; + rtm.rtm_flags = RTF_UP | RTF_GATEWAY; + rtm.rtm_version = RTM_VERSION; + rtm.rtm_seq = ++seq; + rtm.rtm_addrs = rtm_addrs; + + so_dst.sa_family = AF_INET; + so_mask.sa_family = AF_INET; + + NEXTADDR(RTA_DST, so_dst); + NEXTADDR(RTA_NETMASK, so_mask); + + rtm.rtm_msglen = l = cp - (char *)&m_rtmsg; + + s = socket(PF_ROUTE, SOCK_RAW, 0); + + if (write(s, (char *)&m_rtmsg, l) < 0) { + close(s); + return FAILED; + } + + do { + l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg)); + } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid)); + + close(s); + + msg_hdr = &rtm; + + cp = ((char *)(msg_hdr + 1)); + if (msg_hdr->rtm_addrs) { + for (i = 1; i; i <<= 1) + if (i & msg_hdr->rtm_addrs) { + sa = (struct sockaddr *)cp; + if (i == RTA_GATEWAY ) + gate = sa; + + cp += sizeof(struct sockaddr); + } + } else { + return FAILED; + } + + + if (gate != NULL ) { + *addr = ((struct sockaddr_in *)gate)->sin_addr.s_addr; + return SUCCESS; + } else { + return FAILED; + } +} + +#elif defined(USE_WIN32_CODE) + +int getdefaultgateway(in_addr_t * addr) +{ + HKEY networkCardsKey; + HKEY networkCardKey; + HKEY interfacesKey; + HKEY interfaceKey; + DWORD i = 0; + DWORD numSubKeys = 0; + TCHAR keyName[MAX_KEY_LENGTH]; + DWORD keyNameLength = MAX_KEY_LENGTH; + TCHAR keyValue[MAX_VALUE_LENGTH]; + DWORD keyValueLength = MAX_VALUE_LENGTH; + DWORD keyValueType = REG_SZ; + TCHAR gatewayValue[MAX_VALUE_LENGTH]; + DWORD gatewayValueLength = MAX_VALUE_LENGTH; + DWORD gatewayValueType = REG_MULTI_SZ; + int done = 0; + + //const char * networkCardsPath = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards"; + //const char * interfacesPath = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces"; +#ifdef UNICODE + LPCTSTR networkCardsPath = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards"; + LPCTSTR interfacesPath = L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces"; +#define STR_SERVICENAME L"ServiceName" +#define STR_DHCPDEFAULTGATEWAY L"DhcpDefaultGateway" +#define STR_DEFAULTGATEWAY L"DefaultGateway" +#else + LPCTSTR networkCardsPath = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards"; + LPCTSTR interfacesPath = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces"; +#define STR_SERVICENAME "ServiceName" +#define STR_DHCPDEFAULTGATEWAY "DhcpDefaultGateway" +#define STR_DEFAULTGATEWAY "DefaultGateway" +#endif + // The windows registry lists its primary network devices in the following location: + // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards + // + // Each network device has its own subfolder, named with an index, with various properties: + // -NetworkCards + // -5 + // -Description = Broadcom 802.11n Network Adapter + // -ServiceName = {E35A72F8-5065-4097-8DFE-C7790774EE4D} + // -8 + // -Description = Marvell Yukon 88E8058 PCI-E Gigabit Ethernet Controller + // -ServiceName = {86226414-5545-4335-A9D1-5BD7120119AD} + // + // The above service name is the name of a subfolder within: + // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces + // + // There may be more subfolders in this interfaces path than listed in the network cards path above: + // -Interfaces + // -{3a539854-6a70-11db-887c-806e6f6e6963} + // -DhcpIPAddress = 0.0.0.0 + // -[more] + // -{E35A72F8-5065-4097-8DFE-C7790774EE4D} + // -DhcpIPAddress = 10.0.1.4 + // -DhcpDefaultGateway = 10.0.1.1 + // -[more] + // -{86226414-5545-4335-A9D1-5BD7120119AD} + // -DhcpIpAddress = 10.0.1.5 + // -DhcpDefaultGateay = 10.0.1.1 + // -[more] + // + // In order to extract this information, we enumerate each network card, and extract the ServiceName value. + // This is then used to open the interface subfolder, and attempt to extract a DhcpDefaultGateway value. + // Once one is found, we're done. + // + // It may be possible to simply enumerate the interface folders until we find one with a DhcpDefaultGateway value. + // However, the technique used is the technique most cited on the web, and we assume it to be more correct. + + if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, // Open registry key or predifined key + networkCardsPath, // Name of registry subkey to open + 0, // Reserved - must be zero + KEY_READ, // Mask - desired access rights + &networkCardsKey)) // Pointer to output key + { + // Unable to open network cards keys + return -1; + } + + if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, // Open registry key or predefined key + interfacesPath, // Name of registry subkey to open + 0, // Reserved - must be zero + KEY_READ, // Mask - desired access rights + &interfacesKey)) // Pointer to output key + { + // Unable to open interfaces key + RegCloseKey(networkCardsKey); + return -1; + } + + // Figure out how many subfolders are within the NetworkCards folder + RegQueryInfoKey(networkCardsKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + + //printf( "Number of subkeys: %u\n", (unsigned int)numSubKeys); + + // Enumrate through each subfolder within the NetworkCards folder + for(i = 0; i < numSubKeys && !done; i++) + { + keyNameLength = MAX_KEY_LENGTH; + if(ERROR_SUCCESS == RegEnumKeyEx(networkCardsKey, // Open registry key + i, // Index of subkey to retrieve + keyName, // Buffer that receives the name of the subkey + &keyNameLength, // Variable that receives the size of the above buffer + NULL, // Reserved - must be NULL + NULL, // Buffer that receives the class string + NULL, // Variable that receives the size of the above buffer + NULL)) // Variable that receives the last write time of subkey + { + if(RegOpenKeyEx(networkCardsKey, keyName, 0, KEY_READ, &networkCardKey) == ERROR_SUCCESS) + { + keyValueLength = MAX_VALUE_LENGTH; + if(ERROR_SUCCESS == RegQueryValueEx(networkCardKey, // Open registry key + STR_SERVICENAME, // Name of key to query + NULL, // Reserved - must be NULL + &keyValueType, // Receives value type + (LPBYTE)keyValue, // Receives value + &keyValueLength)) // Receives value length in bytes + { +// printf("keyValue: %s\n", keyValue); + if(RegOpenKeyEx(interfacesKey, keyValue, 0, KEY_READ, &interfaceKey) == ERROR_SUCCESS) + { + gatewayValueLength = MAX_VALUE_LENGTH; + if(ERROR_SUCCESS == RegQueryValueEx(interfaceKey, // Open registry key + STR_DHCPDEFAULTGATEWAY, // Name of key to query + NULL, // Reserved - must be NULL + &gatewayValueType, // Receives value type + (LPBYTE)gatewayValue, // Receives value + &gatewayValueLength)) // Receives value length in bytes + { + // Check to make sure it's a string + if((gatewayValueType == REG_MULTI_SZ || gatewayValueType == REG_SZ) && (gatewayValueLength > 1)) + { + //printf("gatewayValue: %s\n", gatewayValue); + done = 1; + } + } + else if(ERROR_SUCCESS == RegQueryValueEx(interfaceKey, // Open registry key + STR_DEFAULTGATEWAY, // Name of key to query + NULL, // Reserved - must be NULL + &gatewayValueType, // Receives value type + (LPBYTE)gatewayValue,// Receives value + &gatewayValueLength)) // Receives value length in bytes + { + // Check to make sure it's a string + if((gatewayValueType == REG_MULTI_SZ || gatewayValueType == REG_SZ) && (gatewayValueLength > 1)) + { + //printf("gatewayValue: %s\n", gatewayValue); + done = 1; + } + } + RegCloseKey(interfaceKey); + } + } + RegCloseKey(networkCardKey); + } + } + } + + RegCloseKey(interfacesKey); + RegCloseKey(networkCardsKey); + + if(done) + { +#if UNICODE + char tmp[32]; + for(i = 0; i < 32; i++) { + tmp[i] = (char)gatewayValue[i]; + if(!tmp[i]) + break; + } + tmp[31] = '\0'; + *addr = inet_addr(tmp); +#else + *addr = inet_addr(gatewayValue); +#endif + return 0; + } + + return -1; +} + +#elif defined(USE_WIN32_CODE_2) + +int getdefaultgateway(in_addr_t *addr) +{ + MIB_IPFORWARDROW ip_forward; + memset(&ip_forward, 0, sizeof(ip_forward)); + if(GetBestRoute(inet_addr("0.0.0.0"), 0, &ip_forward) != NO_ERROR) + return -1; + *addr = ip_forward.dwForwardNextHop; + return 0; +} + +#elif defined(USE_HAIKU_CODE) + +int getdefaultgateway(in_addr_t *addr) +{ + int fd, ret = -1; + struct ifconf config; + void *buffer = NULL; + struct ifreq *interface; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + return -1; + } + if (ioctl(fd, SIOCGRTSIZE, &config, sizeof(config)) != 0) { + goto fail; + } + if (config.ifc_value < 1) { + goto fail; /* No routes */ + } + if ((buffer = malloc(config.ifc_value)) == NULL) { + goto fail; + } + config.ifc_len = config.ifc_value; + config.ifc_buf = buffer; + if (ioctl(fd, SIOCGRTTABLE, &config, sizeof(config)) != 0) { + goto fail; + } + for (interface = buffer; + (uint8_t *)interface < (uint8_t *)buffer + config.ifc_len; ) { + struct route_entry route = interface->ifr_route; + int intfSize; + if (route.flags & (RTF_GATEWAY | RTF_DEFAULT)) { + *addr = ((struct sockaddr_in *)route.gateway)->sin_addr.s_addr; + ret = 0; + break; + } + intfSize = sizeof(route) + IF_NAMESIZE; + if (route.destination != NULL) { + intfSize += route.destination->sa_len; + } + if (route.mask != NULL) { + intfSize += route.mask->sa_len; + } + if (route.gateway != NULL) { + intfSize += route.gateway->sa_len; + } + interface = (struct ifreq *)((uint8_t *)interface + intfSize); + } +fail: + free(buffer); + close(fd); + return ret; +} + +#else /* fallback */ + +int getdefaultgateway(in_addr_t * addr) +{ + (void)addr; + return -1; +} + +#endif diff --git a/src/getgateway.h b/src/getgateway.h new file mode 100644 index 0000000000000..90322a366e057 --- /dev/null +++ b/src/getgateway.h @@ -0,0 +1,47 @@ +/* $Id: getgateway.h,v 1.7 2013/09/10 20:09:04 nanard Exp $ */ +/* libnatpmp +Copyright (c) 2007-2014, Thomas BERNARD +All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef __GETGATEWAY_H__ +#define __GETGATEWAY_H__ + +#ifdef WIN32 +#if !defined(_MSC_VER) || _MSC_VER >= 1600 +#include +#else +typedef unsigned long uint32_t; +typedef unsigned short uint16_t; +#endif +#define in_addr_t uint32_t +#endif +/* #include "declspec.h" */ + +/* getdefaultgateway() : + * return value : + * 0 : success + * -1 : failure */ +/* NATPMP_LIBSPEC */ +int getdefaultgateway(in_addr_t * addr); + +#endif diff --git a/src/natpmp.c b/src/natpmp.c new file mode 100644 index 0000000000000..dcde82fc1a6b0 --- /dev/null +++ b/src/natpmp.c @@ -0,0 +1,354 @@ +#ifdef __linux__ +#define _BSD_SOURCE 1 +#endif +#include +#include +#if !defined(_MSC_VER) +#include +#endif +#ifdef WIN32 +#include +#include +#include +#include +#ifndef EWOULDBLOCK +#define EWOULDBLOCK WSAEWOULDBLOCK +#endif +#ifndef ECONNREFUSED +#define ECONNREFUSED WSAECONNREFUSED +#endif +#include +#define gettimeofday natpmp_gettimeofday +#else +#include +#include +#include +#include +#include +#define closesocket close +#endif +#include +#include +#include + +NATPMP_LIBSPEC int initnatpmp(natpmp_t * p, int forcegw, in_addr_t forcedgw) +{ +#ifdef WIN32 + u_long ioctlArg = 1; +#else + int flags; +#endif + struct sockaddr_in addr; + if(!p) + return NATPMP_ERR_INVALIDARGS; + memset(p, 0, sizeof(natpmp_t)); + p->s = socket(PF_INET, SOCK_DGRAM, 0); + if(p->s < 0) + return NATPMP_ERR_SOCKETERROR; +#ifdef WIN32 + if(ioctlsocket(p->s, FIONBIO, &ioctlArg) == SOCKET_ERROR) + return NATPMP_ERR_FCNTLERROR; +#else + if((flags = fcntl(p->s, F_GETFL, 0)) < 0) + return NATPMP_ERR_FCNTLERROR; + if(fcntl(p->s, F_SETFL, flags | O_NONBLOCK) < 0) + return NATPMP_ERR_FCNTLERROR; +#endif + + if(forcegw) { + p->gateway = forcedgw; + } else { + if(getdefaultgateway(&(p->gateway)) < 0) + return NATPMP_ERR_CANNOTGETGATEWAY; + } + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(NATPMP_PORT); + addr.sin_addr.s_addr = p->gateway; + if(connect(p->s, (struct sockaddr *)&addr, sizeof(addr)) < 0) + return NATPMP_ERR_CONNECTERR; + return 0; +} + +NATPMP_LIBSPEC int closenatpmp(natpmp_t * p) +{ + if(!p) + return NATPMP_ERR_INVALIDARGS; + if(closesocket(p->s) < 0) + return NATPMP_ERR_CLOSEERR; + return 0; +} + +int sendpendingrequest(natpmp_t * p) +{ + int r; +/* struct sockaddr_in addr;*/ + if(!p) + return NATPMP_ERR_INVALIDARGS; +/* memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(NATPMP_PORT); + addr.sin_addr.s_addr = p->gateway; + r = (int)sendto(p->s, p->pending_request, p->pending_request_len, 0, + (struct sockaddr *)&addr, sizeof(addr));*/ + r = (int)send(p->s, p->pending_request, p->pending_request_len, 0); + return (r<0) ? NATPMP_ERR_SENDERR : r; +} + +int sendnatpmprequest(natpmp_t * p) +{ + int n; + if(!p) + return NATPMP_ERR_INVALIDARGS; + /* TODO : check if no request is allready pending */ + p->has_pending_request = 1; + p->try_number = 1; + n = sendpendingrequest(p); + gettimeofday(&p->retry_time, NULL); // check errors ! + p->retry_time.tv_usec += 250000; /* add 250ms */ + if(p->retry_time.tv_usec >= 1000000) { + p->retry_time.tv_usec -= 1000000; + p->retry_time.tv_sec++; + } + return n; +} + +NATPMP_LIBSPEC int getnatpmprequesttimeout(natpmp_t * p, struct timeval * timeout) +{ + struct timeval now; + if(!p || !timeout) + return NATPMP_ERR_INVALIDARGS; + if(!p->has_pending_request) + return NATPMP_ERR_NOPENDINGREQ; + if(gettimeofday(&now, NULL) < 0) + return NATPMP_ERR_GETTIMEOFDAYERR; + timeout->tv_sec = p->retry_time.tv_sec - now.tv_sec; + timeout->tv_usec = p->retry_time.tv_usec - now.tv_usec; + if(timeout->tv_usec < 0) { + timeout->tv_usec += 1000000; + timeout->tv_sec--; + } + return 0; +} + +NATPMP_LIBSPEC int sendpublicaddressrequest(natpmp_t * p) +{ + if(!p) + return NATPMP_ERR_INVALIDARGS; + //static const unsigned char request[] = { 0, 0 }; + p->pending_request[0] = 0; + p->pending_request[1] = 0; + p->pending_request_len = 2; + // TODO: return 0 instead of sizeof(request) ?? + return sendnatpmprequest(p); +} + +NATPMP_LIBSPEC int sendnewportmappingrequest(natpmp_t * p, uint16_t privateport, + uint16_t publicport, uint32_t lifetime) +{ + if(!p) + return NATPMP_ERR_INVALIDARGS; + p->pending_request[0] = 0; + p->pending_request[1] = 1; /* TCP only. */ + p->pending_request[2] = 0; + p->pending_request[3] = 0; + /* break strict-aliasing rules : + *((uint16_t *)(p->pending_request + 4)) = htons(privateport); */ + p->pending_request[4] = (privateport >> 8) & 0xff; + p->pending_request[5] = privateport & 0xff; + /* break stric-aliasing rules : + *((uint16_t *)(p->pending_request + 6)) = htons(publicport); */ + p->pending_request[6] = (publicport >> 8) & 0xff; + p->pending_request[7] = publicport & 0xff; + /* break stric-aliasing rules : + *((uint32_t *)(p->pending_request + 8)) = htonl(lifetime); */ + p->pending_request[8] = (lifetime >> 24) & 0xff; + p->pending_request[9] = (lifetime >> 16) & 0xff; + p->pending_request[10] = (lifetime >> 8) & 0xff; + p->pending_request[11] = lifetime & 0xff; + p->pending_request_len = 12; + return sendnatpmprequest(p); +} + +NATPMP_LIBSPEC int readnatpmpresponse(natpmp_t * p, natpmpresp_t * response) +{ + unsigned char buf[16]; + struct sockaddr_in addr; + socklen_t addrlen = sizeof(addr); + int n; + if(!p) + return NATPMP_ERR_INVALIDARGS; + n = recvfrom(p->s, buf, sizeof(buf), 0, + (struct sockaddr *)&addr, &addrlen); + if(n<0) +#ifdef WIN32 + switch(WSAGetLastError()) { +#else + switch(errno) { +#endif + /*case EAGAIN:*/ + case EWOULDBLOCK: + n = NATPMP_TRYAGAIN; + break; + case ECONNREFUSED: + n = NATPMP_ERR_NOGATEWAYSUPPORT; + break; + default: + n = NATPMP_ERR_RECVFROM; + } + /* check that addr is correct (= gateway) */ + else if(addr.sin_addr.s_addr != p->gateway) + n = NATPMP_ERR_WRONGPACKETSOURCE; + else { + response->resultcode = ntohs(*((uint16_t *)(buf + 2))); + response->epoch = ntohl(*((uint32_t *)(buf + 4))); + if(buf[0] != 0) + n = NATPMP_ERR_UNSUPPORTEDVERSION; + else if(buf[1] < 128 || buf[1] > 130) + n = NATPMP_ERR_UNSUPPORTEDOPCODE; + else if(response->resultcode != 0) { + switch(response->resultcode) { + case 1: + n = NATPMP_ERR_UNSUPPORTEDVERSION; + break; + case 2: + n = NATPMP_ERR_NOTAUTHORIZED; + break; + case 3: + n = NATPMP_ERR_NETWORKFAILURE; + break; + case 4: + n = NATPMP_ERR_OUTOFRESOURCES; + break; + case 5: + n = NATPMP_ERR_UNSUPPORTEDOPCODE; + break; + default: + n = NATPMP_ERR_UNDEFINEDERROR; + } + } else { + response->type = buf[1] & 0x7f; + if(buf[1] == 128) + //response->publicaddress.addr = *((uint32_t *)(buf + 8)); + response->pnu.publicaddress.addr.s_addr = *((uint32_t *)(buf + 8)); + else { + response->pnu.newportmapping.privateport = ntohs(*((uint16_t *)(buf + 8))); + response->pnu.newportmapping.mappedpublicport = ntohs(*((uint16_t *)(buf + 10))); + response->pnu.newportmapping.lifetime = ntohl(*((uint32_t *)(buf + 12))); + } + n = 0; + } + } + return n; +} + +NATPMP_LIBSPEC int readnatpmpresponseorretry(natpmp_t * p, natpmpresp_t * response) +{ + int n; + if(!p || !response) + return NATPMP_ERR_INVALIDARGS; + if(!p->has_pending_request) + return NATPMP_ERR_NOPENDINGREQ; + n = readnatpmpresponse(p, response); + if(n<0) { + if(n==NATPMP_TRYAGAIN) { + struct timeval now; + gettimeofday(&now, NULL); // check errors ! + if(timercmp(&now, &p->retry_time, >=)) { + int delay, r; + if(p->try_number >= 9) { + return NATPMP_ERR_NOGATEWAYSUPPORT; + } + /*printf("retry! %d\n", p->try_number);*/ + delay = 250 * (1<try_number); // ms + /*for(i=0; itry_number; i++) + delay += delay;*/ + p->retry_time.tv_sec += (delay / 1000); + p->retry_time.tv_usec += (delay % 1000) * 1000; + if(p->retry_time.tv_usec >= 1000000) { + p->retry_time.tv_usec -= 1000000; + p->retry_time.tv_sec++; + } + p->try_number++; + r = sendpendingrequest(p); + if(r<0) + return r; + } + } + } else { + p->has_pending_request = 0; + } + return n; +} + +#ifdef ENABLE_STRNATPMPERR +NATPMP_LIBSPEC const char * strnatpmperr(int r) +{ + const char * s; + switch(r) { + case NATPMP_ERR_INVALIDARGS: + s = "invalid arguments"; + break; + case NATPMP_ERR_SOCKETERROR: + s = "socket() failed"; + break; + case NATPMP_ERR_CANNOTGETGATEWAY: + s = "cannot get default gateway ip address"; + break; + case NATPMP_ERR_CLOSEERR: +#ifdef WIN32 + s = "closesocket() failed"; +#else + s = "close() failed"; +#endif + break; + case NATPMP_ERR_RECVFROM: + s = "recvfrom() failed"; + break; + case NATPMP_ERR_NOPENDINGREQ: + s = "no pending request"; + break; + case NATPMP_ERR_NOGATEWAYSUPPORT: + s = "the gateway does not support nat-pmp"; + break; + case NATPMP_ERR_CONNECTERR: + s = "connect() failed"; + break; + case NATPMP_ERR_WRONGPACKETSOURCE: + s = "packet not received from the default gateway"; + break; + case NATPMP_ERR_SENDERR: + s = "send() failed"; + break; + case NATPMP_ERR_FCNTLERROR: + s = "fcntl() failed"; + break; + case NATPMP_ERR_GETTIMEOFDAYERR: + s = "gettimeofday() failed"; + break; + case NATPMP_ERR_UNSUPPORTEDVERSION: + s = "unsupported nat-pmp version error from server"; + break; + case NATPMP_ERR_UNSUPPORTEDOPCODE: + s = "unsupported nat-pmp opcode error from server"; + break; + case NATPMP_ERR_UNDEFINEDERROR: + s = "undefined nat-pmp server error"; + break; + case NATPMP_ERR_NOTAUTHORIZED: + s = "not authorized"; + break; + case NATPMP_ERR_NETWORKFAILURE: + s = "network failure"; + break; + case NATPMP_ERR_OUTOFRESOURCES: + s = "nat-pmp server out of resources"; + break; + default: + s = "Unknown libnatpmp error"; + } + return s; +} +#endif + diff --git a/src/natpmp.h b/src/natpmp.h new file mode 100644 index 0000000000000..feb519d3a4613 --- /dev/null +++ b/src/natpmp.h @@ -0,0 +1,182 @@ +#ifndef __NATPMP_H__ +#define __NATPMP_H__ + +#include + +#if !defined(_MSC_VER) +#include +#endif + +#ifdef WIN32 +#include +#if !defined(_MSC_VER) || _MSC_VER >= 1600 +#include +#else /* !defined(_MSC_VER) || _MSC_VER >= 1600 */ +typedef unsigned long uint32_t; +typedef unsigned short uint16_t; +#endif /* !defined(_MSC_VER) || _MSC_VER >= 1600 */ +#define in_addr_t uint32_t +#else +#include +#endif + +#include + +typedef struct { + int s; /* socket */ + in_addr_t gateway; /* default gateway (IPv4) */ + int has_pending_request; + unsigned char pending_request[12]; + int pending_request_len; + int try_number; + struct timeval retry_time; +} natpmp_t; + +typedef struct { + uint16_t type; /* NATPMP_RESPTYPE_* */ + uint16_t resultcode; /* NAT-PMP response code */ + uint32_t epoch; /* Seconds since start of epoch */ + union { + struct { + //in_addr_t addr; + struct in_addr addr; + } publicaddress; + struct { + uint16_t privateport; + uint16_t mappedpublicport; + uint32_t lifetime; + } newportmapping; + } pnu; +} natpmpresp_t; + +/* possible values for type field of natpmpresp_t */ +#define NATPMP_RESPTYPE_PUBLICADDRESS (0) +// #define NATPMP_RESPTYPE_UDPPORTMAPPING (1) +#define NATPMP_RESPTYPE_TCPPORTMAPPING (1) + +/* return values */ +/* NATPMP_ERR_INVALIDARGS : invalid arguments passed to the function */ +#define NATPMP_ERR_INVALIDARGS (-1) +/* NATPMP_ERR_SOCKETERROR : socket() failed. check errno for details */ +#define NATPMP_ERR_SOCKETERROR (-2) +/* NATPMP_ERR_CANNOTGETGATEWAY : can't get default gateway IP */ +#define NATPMP_ERR_CANNOTGETGATEWAY (-3) +/* NATPMP_ERR_CLOSEERR : close() failed. check errno for details */ +#define NATPMP_ERR_CLOSEERR (-4) +/* NATPMP_ERR_RECVFROM : recvfrom() failed. check errno for details */ +#define NATPMP_ERR_RECVFROM (-5) +/* NATPMP_ERR_NOPENDINGREQ : readnatpmpresponseorretry() called while + * no NAT-PMP request was pending */ +#define NATPMP_ERR_NOPENDINGREQ (-6) +/* NATPMP_ERR_NOGATEWAYSUPPORT : the gateway does not support NAT-PMP */ +#define NATPMP_ERR_NOGATEWAYSUPPORT (-7) +/* NATPMP_ERR_CONNECTERR : connect() failed. check errno for details */ +#define NATPMP_ERR_CONNECTERR (-8) +/* NATPMP_ERR_WRONGPACKETSOURCE : packet not received from the network gateway */ +#define NATPMP_ERR_WRONGPACKETSOURCE (-9) +/* NATPMP_ERR_SENDERR : send() failed. check errno for details */ +#define NATPMP_ERR_SENDERR (-10) +/* NATPMP_ERR_FCNTLERROR : fcntl() failed. check errno for details */ +#define NATPMP_ERR_FCNTLERROR (-11) +/* NATPMP_ERR_GETTIMEOFDAYERR : gettimeofday() failed. check errno for details */ +#define NATPMP_ERR_GETTIMEOFDAYERR (-12) + +/* */ +#define NATPMP_ERR_UNSUPPORTEDVERSION (-14) +#define NATPMP_ERR_UNSUPPORTEDOPCODE (-15) + +/* Errors from the server : */ +#define NATPMP_ERR_UNDEFINEDERROR (-49) +#define NATPMP_ERR_NOTAUTHORIZED (-51) +#define NATPMP_ERR_NETWORKFAILURE (-52) +#define NATPMP_ERR_OUTOFRESOURCES (-53) + +/* NATPMP_TRYAGAIN : no data available for the moment. try again later */ +#define NATPMP_TRYAGAIN (-100) + +#ifdef __cplusplus +extern "C" { +#endif + +/* initnatpmp() + * initialize a natpmp_t object + * With forcegw=1 the gateway is not detected automaticaly. + * Return values : + * 0 = OK + * NATPMP_ERR_INVALIDARGS + * NATPMP_ERR_SOCKETERROR + * NATPMP_ERR_FCNTLERROR + * NATPMP_ERR_CANNOTGETGATEWAY + * NATPMP_ERR_CONNECTERR */ +NATPMP_LIBSPEC int initnatpmp(natpmp_t * p, int forcegw, in_addr_t forcedgw); + +/* closenatpmp() + * close resources associated with a natpmp_t object + * Return values : + * 0 = OK + * NATPMP_ERR_INVALIDARGS + * NATPMP_ERR_CLOSEERR */ +NATPMP_LIBSPEC int closenatpmp(natpmp_t * p); + +/* sendpublicaddressrequest() + * send a public address NAT-PMP request to the network gateway + * Return values : + * 2 = OK (size of the request) + * NATPMP_ERR_INVALIDARGS + * NATPMP_ERR_SENDERR */ +NATPMP_LIBSPEC int sendpublicaddressrequest(natpmp_t * p); + +/* sendnewportmappingrequest() + * send a new port mapping NAT-PMP request to the network gateway + * Arguments : + * protocol is either NATPMP_PROTOCOL_TCP or NATPMP_PROTOCOL_UDP, + * lifetime is in seconds. + * To remove a port mapping, set lifetime to zero. + * To remove all port mappings to the host, set lifetime and both ports + * to zero. + * Return values : + * 12 = OK (size of the request) + * NATPMP_ERR_INVALIDARGS + * NATPMP_ERR_SENDERR */ +NATPMP_LIBSPEC int sendnewportmappingrequest(natpmp_t * p, + uint16_t privateport, uint16_t publicport, + uint32_t lifetime); + +/* getnatpmprequesttimeout() + * fills the timeval structure with the timeout duration of the + * currently pending NAT-PMP request. + * Return values : + * 0 = OK + * NATPMP_ERR_INVALIDARGS + * NATPMP_ERR_GETTIMEOFDAYERR + * NATPMP_ERR_NOPENDINGREQ */ +NATPMP_LIBSPEC int getnatpmprequesttimeout(natpmp_t * p, struct timeval * timeout); + +/* readnatpmpresponseorretry() + * fills the natpmpresp_t structure if possible + * Return values : + * 0 = OK + * NATPMP_TRYAGAIN + * NATPMP_ERR_INVALIDARGS + * NATPMP_ERR_NOPENDINGREQ + * NATPMP_ERR_NOGATEWAYSUPPORT + * NATPMP_ERR_RECVFROM + * NATPMP_ERR_WRONGPACKETSOURCE + * NATPMP_ERR_UNSUPPORTEDVERSION + * NATPMP_ERR_UNSUPPORTEDOPCODE + * NATPMP_ERR_NOTAUTHORIZED + * NATPMP_ERR_NETWORKFAILURE + * NATPMP_ERR_OUTOFRESOURCES + * NATPMP_ERR_UNSUPPORTEDOPCODE + * NATPMP_ERR_UNDEFINEDERROR */ +NATPMP_LIBSPEC int readnatpmpresponseorretry(natpmp_t * p, natpmpresp_t * response); + +#ifdef ENABLE_STRNATPMPERR +NATPMP_LIBSPEC const char * strnatpmperr(int t); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/net.cpp b/src/net.cpp index 682f47bff234b..d8ec20515a55d 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -8,6 +8,7 @@ #endif #include +#include #include #include @@ -27,10 +28,7 @@ #endif #ifdef USE_UPNP -#include -#include -#include -#include +#include #endif @@ -1462,106 +1460,120 @@ void CConnman::WakeMessageHandler() void ThreadMapPort() { std::string port = strprintf("%u", GetListenPort()); - const char * multicastif = nullptr; - const char * minissdpdpath = nullptr; - struct UPNPDev * devlist = nullptr; - char lanaddr[64]; - -#ifndef UPNPDISCOVER_SUCCESS - /* miniupnpc 1.5 */ - devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0); -#elif MINIUPNPC_API_VERSION < 14 - /* miniupnpc 1.6 */ - int error = 0; - devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error); -#else - /* miniupnpc 1.9.20150730 */ - int error = 0; - devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, 2, &error); -#endif - struct UPNPUrls urls; - struct IGDdatas data; + natpmp_t natpmp; + natpmpresp_t response; int r; - - r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); - if (r == 1) - { - if (fDiscover) { - char externalIPAddress[40]; - r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress); - if(r != UPNPCOMMAND_SUCCESS) - LogPrintf("UPnP: GetExternalIPAddress() returned %d\n", r); - else - { - if(externalIPAddress[0]) - { - CNetAddr resolved; - if(LookupHost(externalIPAddress, resolved, false)) { - LogPrintf("UPnP: ExternalIPAddress = %s\n", resolved.ToString().c_str()); - AddLocal(resolved, LOCAL_UPNP); - } + int sav_errno; + struct timeval timeout; + fd_set fds; + int i; + int protocol = 0; + uint16_t privateport = std::atoi(port); + uint16_t publicport = std::atoi(port); + uint32_t lifetime = 3600; + int command = 0; + int forcegw = 0; + in_addr_t gateway = 0; + struct in_addr gateway_in_use; + + + try{ + /* initnatpmp() */ + r = initnatpmp(&natpmp, forcegw, gateway); + LogPrintf("NATPMP: initnatpmp returned %d\n", r); + + gateway_in_use.s_addr = natpmp.gateway; + + /* sendpublicaddressrequest() */ + r = sendpublicaddressrequest(&natpmp); + LogPrintf("NATPMP: sendpublicaddressrequest returned %d\n", r); + + do { + FD_ZERO(&fds); + FD_SET(natpmp.s, &fds); + getnatpmprequesttimeout(&natpmp, &timeout); + r = select(FD_SETSIZE, &fds, nullptr, nullptr, &timeout); + if(r>=0) { + r = readnatpmpresponseorretry(&natpmp, &response); + sav_errno = errno; + LogPrintf("NATPMP: readnatpmpresponseorretry returned %d (%s)\n", + r, r==0?"OK":(r==NATPMP_TRYAGAIN?"TRY AGAIN":"FAILED")); + + if(r<0 && r!=NATPMP_TRYAGAIN) { +#ifdef ENABLE_STRNATPMPERR + LogPrintf("NATPMP: readnatpmpresponseorretry() failed : %s\n", + strnatpmperr(r)); +#endif + LogPrintf(" errno=%d '%s'\n", + sav_errno, strerror(sav_errno)); } - else - LogPrintf("UPnP: GetExternalIPAddress failed.\n"); + }else{ + LogPrintf("NATPMP: Error with select()\n"); } + } while(r==NATPMP_TRYAGAIN); + + LogPrintf("NATPMP: Public IP address : %s\n", + inet_ntoa(response.pnu.publicaddress.addr)); + + + /* sendnewportmappingrequest() */ + r = sendnewportmappingrequest(&natpmp, privateport, + publicport, lifetime); + LogPrintf("NATPMP: sendnewportmappingrequest returned %d (%s)\n", + r, r==12?"SUCCESS":"FAILED"); + + do { + FD_ZERO(&fds); + FD_SET(natpmp.s, &fds); + getnatpmprequesttimeout(&natpmp, &timeout); + select(FD_SETSIZE, &fds, nullptr, nullptr, &timeout); + r = readnatpmpresponseorretry(&natpmp, &response); + LogPrintf("NATPMP: readnatpmpresponseorretry returned %d (%s)\n", + r, r==0?"OK":(r==NATPMP_TRYAGAIN?"TRY AGAIN":"FAILED")); + } while(r==NATPMP_TRYAGAIN); + + if(r<0) { +#ifdef ENABLE_STRNATPMPERR + LogPrintf("NATPMP: readnatpmpresponseorretry() failed : %s\n", + strnatpmperr(r)); +#endif } - std::string strDesc = "Bitcoin " + FormatFullVersion(); - - try { - while (true) { -#ifndef UPNPDISCOVER_SUCCESS - /* miniupnpc 1.5 */ - r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, - port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0); -#else - /* miniupnpc 1.6 */ - r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, - port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0"); -#endif + LogPrintf("Mapped public port %hu protocol %s to local port %hu " + "liftime %u\n", + response.pnu.newportmapping.mappedpublicport, + "TCP", + response.pnu.newportmapping.privateport, + response.pnu.newportmapping.lifetime); + } + catch (const boost::thread_interrupted&) + { + r = closenatpmp(&natpmp); + LogPrintf("NATPMP: closenatpmp() returned %d (%s)\n", + r, r==0?"SUCCESS":"FAILED"); - if(r!=UPNPCOMMAND_SUCCESS) - LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", - port, port, lanaddr, r, strupnperror(r)); - else - LogPrintf("UPnP Port Mapping successful.\n"); + throw; - MilliSleep(20*60*1000); // Refresh every 20 minutes - } - } - catch (const boost::thread_interrupted&) - { - r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0); - LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r); - freeUPNPDevlist(devlist); devlist = nullptr; - FreeUPNPUrls(&urls); - throw; - } - } else { - LogPrintf("No valid UPnP IGDs found\n"); - freeUPNPDevlist(devlist); devlist = nullptr; - if (r != 0) - FreeUPNPUrls(&urls); } } void MapPort(bool fUseUPnP) { - static std::unique_ptr upnp_thread; + static std::unique_ptr natpmp_thread; if (fUseUPnP) { - if (upnp_thread) { - upnp_thread->interrupt(); - upnp_thread->join(); + if (natpmp_thread) { + natpmp_thread->interrupt(); + natpmp_thread->join(); } - upnp_thread.reset(new boost::thread(boost::bind(&TraceThread, "upnp", &ThreadMapPort))); + natpmp_thread.reset(new boost::thread(boost::bind(&TraceThread, "upnp", &ThreadMapPort))); } - else if (upnp_thread) { - upnp_thread->interrupt(); - upnp_thread->join(); - upnp_thread.reset(); + else if (natpmp_thread) { + natpmp_thread->interrupt(); + natpmp_thread->join(); + natpmp_thread.reset(); } } @@ -1570,8 +1582,7 @@ void MapPort(bool) { // Intentionally left blank. } -#endif - +#endif // for UPNP diff --git a/src/wingettimeofday.c b/src/wingettimeofday.c new file mode 100644 index 0000000000000..636807c3f5797 --- /dev/null +++ b/src/wingettimeofday.c @@ -0,0 +1,60 @@ +/* $Id: wingettimeofday.c,v 1.6 2013/09/10 20:13:26 nanard Exp $ */ +/* libnatpmp +Copyright (c) 2007-2013, Thomas BERNARD +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +#ifdef WIN32 +#if defined(_MSC_VER) +struct timeval { + long tv_sec; + long tv_usec; +}; +#else +#include +#endif + +typedef struct _FILETIME { + unsigned long dwLowDateTime; + unsigned long dwHighDateTime; +} FILETIME; + +void __stdcall GetSystemTimeAsFileTime(FILETIME*); + +int natpmp_gettimeofday(struct timeval* p, void* tz /* IGNORED */) { + union { + long long ns100; /*time since 1 Jan 1601 in 100ns units */ + FILETIME ft; + } _now; + + if(!p) + return -1; + GetSystemTimeAsFileTime( &(_now.ft) ); + p->tv_usec =(long)((_now.ns100 / 10LL) % 1000000LL ); + p->tv_sec = (long)((_now.ns100-(116444736000000000LL))/10000000LL); + return 0; +} +#endif + diff --git a/src/wingettimeofday.h b/src/wingettimeofday.h new file mode 100644 index 0000000000000..577b7f5369263 --- /dev/null +++ b/src/wingettimeofday.h @@ -0,0 +1,36 @@ +/* $Id: wingettimeofday.h,v 1.5 2013/09/11 07:22:25 nanard Exp $ */ +/* libnatpmp +Copyright (c) 2007-2013, Thomas BERNARD +All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef __WINGETTIMEOFDAY_H__ +#define __WINGETTIMEOFDAY_H__ +#ifdef WIN32 +#if defined(_MSC_VER) +#include +#else +#include +#endif +int natpmp_gettimeofday(struct timeval* p, void* tz /* IGNORED */); +#endif +#endif From d4d3c05bb2b07023db1c90e995b196e57ca774f5 Mon Sep 17 00:00:00 2001 From: Annanay Date: Mon, 29 Jan 2018 02:04:29 +0530 Subject: [PATCH 02/17] Add license info on some files --- src/natpmp.c | 26 ++++++++++++++++++++++++++ src/natpmp.h | 26 ++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/src/natpmp.c b/src/natpmp.c index dcde82fc1a6b0..6cb1d3c0db794 100644 --- a/src/natpmp.c +++ b/src/natpmp.c @@ -1,3 +1,29 @@ +/* $Id: natpmp.c,v 1.18 2013/11/26 08:47:36 nanard Exp $ */ +/* libnatpmp +Copyright (c) 2007-2013, Thomas BERNARD +All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + #ifdef __linux__ #define _BSD_SOURCE 1 #endif diff --git a/src/natpmp.h b/src/natpmp.h index feb519d3a4613..97bfb0eef2a6b 100644 --- a/src/natpmp.h +++ b/src/natpmp.h @@ -1,3 +1,29 @@ +/* $Id: natpmp.h,v 1.19 2014/04/01 09:39:29 nanard Exp $ */ +/* libnatpmp +Copyright (c) 2007-2014, Thomas BERNARD +All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + #ifndef __NATPMP_H__ #define __NATPMP_H__ From 9fb118e1229f52a454b2047aca73b04496ee53c0 Mon Sep 17 00:00:00 2001 From: Annanay Date: Fri, 9 Mar 2018 14:41:02 +0530 Subject: [PATCH 03/17] Added natpmp.h to Makefile and moved files to subdirectory --- src/{ => natpmp}/getgateway.c | 0 src/{ => natpmp}/getgateway.h | 0 src/{ => natpmp}/natpmp.c | 0 src/{ => natpmp}/natpmp.h | 0 src/{ => natpmp}/wingettimeofday.c | 0 src/{ => natpmp}/wingettimeofday.h | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename src/{ => natpmp}/getgateway.c (100%) rename src/{ => natpmp}/getgateway.h (100%) rename src/{ => natpmp}/natpmp.c (100%) rename src/{ => natpmp}/natpmp.h (100%) rename src/{ => natpmp}/wingettimeofday.c (100%) rename src/{ => natpmp}/wingettimeofday.h (100%) diff --git a/src/getgateway.c b/src/natpmp/getgateway.c similarity index 100% rename from src/getgateway.c rename to src/natpmp/getgateway.c diff --git a/src/getgateway.h b/src/natpmp/getgateway.h similarity index 100% rename from src/getgateway.h rename to src/natpmp/getgateway.h diff --git a/src/natpmp.c b/src/natpmp/natpmp.c similarity index 100% rename from src/natpmp.c rename to src/natpmp/natpmp.c diff --git a/src/natpmp.h b/src/natpmp/natpmp.h similarity index 100% rename from src/natpmp.h rename to src/natpmp/natpmp.h diff --git a/src/wingettimeofday.c b/src/natpmp/wingettimeofday.c similarity index 100% rename from src/wingettimeofday.c rename to src/natpmp/wingettimeofday.c diff --git a/src/wingettimeofday.h b/src/natpmp/wingettimeofday.h similarity index 100% rename from src/wingettimeofday.h rename to src/natpmp/wingettimeofday.h From dae9e0f6b648ffbd04cc4e740eaf4184aa5e5b12 Mon Sep 17 00:00:00 2001 From: Annanay Date: Fri, 9 Mar 2018 20:24:34 +0530 Subject: [PATCH 04/17] Added natpmp/natpmp.h to Makefile.am --- src/Makefile.am | 1 + src/net.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 4b65774fc6f58..1257d7ce1a6bd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -111,6 +111,7 @@ BITCOIN_CORE_H = \ memusage.h \ merkleblock.h \ miner.h \ + natpmp/natpmp.h \ net.h \ net_processing.h \ netaddress.h \ diff --git a/src/net.cpp b/src/net.cpp index d8ec20515a55d..e1ac4dab1c3f6 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -28,7 +28,7 @@ #endif #ifdef USE_UPNP -#include +#include #endif From 25da431c188d2253100a83d87c29d16aaa91104d Mon Sep 17 00:00:00 2001 From: Annanay Date: Sat, 10 Mar 2018 01:27:58 +0530 Subject: [PATCH 05/17] Added natpmp_declspec.h and changed some naming conventions --- src/natpmp/getgateway.c | 32 ++++++++++++++++---------------- src/natpmp/natpmp.c | 6 +++--- src/natpmp/natpmp_declspec.h | 21 +++++++++++++++++++++ 3 files changed, 40 insertions(+), 19 deletions(-) create mode 100644 src/natpmp/natpmp_declspec.h diff --git a/src/natpmp/getgateway.c b/src/natpmp/getgateway.c index 27ab473a6f048..e073a31f218c1 100644 --- a/src/natpmp/getgateway.c +++ b/src/natpmp/getgateway.c @@ -210,7 +210,7 @@ int getdefaultgateway(in_addr_t * addr) sa_tab[i] = sa; sa = (struct sockaddr *)((char *)sa + ROUNDUP(sa->sa_len)); } else { - sa_tab[i] = NULL; + sa_tab[i] = nullptr; } } if( ((rt->rtm_addrs & (RTA_DST|RTA_GATEWAY)) == (RTA_DST|RTA_GATEWAY)) @@ -248,7 +248,7 @@ int getdefaultgateway(in_addr_t *addr) pid_t pid; struct sockaddr so_dst, so_mask; char *cp = m_rtmsg.m_space; - struct sockaddr *gate = NULL, *sa; + struct sockaddr *gate = nullptr, *sa; struct rt_msghdr *msg_hdr; pid = getpid(); @@ -303,7 +303,7 @@ int getdefaultgateway(in_addr_t *addr) } - if (gate != NULL ) { + if (gate != nullptr ) { *addr = ((struct sockaddr_in *)gate)->sin_addr.s_addr; return SUCCESS; } else { @@ -404,7 +404,7 @@ int getdefaultgateway(in_addr_t * addr) } // Figure out how many subfolders are within the NetworkCards folder - RegQueryInfoKey(networkCardsKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + RegQueryInfoKey(networkCardsKey, nullptr, nullptr, nullptr, &numSubKeys, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); //printf( "Number of subkeys: %u\n", (unsigned int)numSubKeys); @@ -416,17 +416,17 @@ int getdefaultgateway(in_addr_t * addr) i, // Index of subkey to retrieve keyName, // Buffer that receives the name of the subkey &keyNameLength, // Variable that receives the size of the above buffer - NULL, // Reserved - must be NULL - NULL, // Buffer that receives the class string - NULL, // Variable that receives the size of the above buffer - NULL)) // Variable that receives the last write time of subkey + nullptr, // Reserved - must be nil + nullptr, // Buffer that receives the class string + nullptr, // Variable that receives the size of the above buffer + nullptr)) // Variable that receives the last write time of subkey { if(RegOpenKeyEx(networkCardsKey, keyName, 0, KEY_READ, &networkCardKey) == ERROR_SUCCESS) { keyValueLength = MAX_VALUE_LENGTH; if(ERROR_SUCCESS == RegQueryValueEx(networkCardKey, // Open registry key STR_SERVICENAME, // Name of key to query - NULL, // Reserved - must be NULL + nullptr, // Reserved - must be nil &keyValueType, // Receives value type (LPBYTE)keyValue, // Receives value &keyValueLength)) // Receives value length in bytes @@ -437,7 +437,7 @@ int getdefaultgateway(in_addr_t * addr) gatewayValueLength = MAX_VALUE_LENGTH; if(ERROR_SUCCESS == RegQueryValueEx(interfaceKey, // Open registry key STR_DHCPDEFAULTGATEWAY, // Name of key to query - NULL, // Reserved - must be NULL + nullptr, // Reserved - must be nil &gatewayValueType, // Receives value type (LPBYTE)gatewayValue, // Receives value &gatewayValueLength)) // Receives value length in bytes @@ -451,7 +451,7 @@ int getdefaultgateway(in_addr_t * addr) } else if(ERROR_SUCCESS == RegQueryValueEx(interfaceKey, // Open registry key STR_DEFAULTGATEWAY, // Name of key to query - NULL, // Reserved - must be NULL + nullptr, // Reserved - must be nil &gatewayValueType, // Receives value type (LPBYTE)gatewayValue,// Receives value &gatewayValueLength)) // Receives value length in bytes @@ -512,7 +512,7 @@ int getdefaultgateway(in_addr_t *addr) { int fd, ret = -1; struct ifconf config; - void *buffer = NULL; + void *buffer = nullptr; struct ifreq *interface; if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { @@ -524,7 +524,7 @@ int getdefaultgateway(in_addr_t *addr) if (config.ifc_value < 1) { goto fail; /* No routes */ } - if ((buffer = malloc(config.ifc_value)) == NULL) { + if ((buffer = malloc(config.ifc_value)) == nullptr) { goto fail; } config.ifc_len = config.ifc_value; @@ -542,13 +542,13 @@ int getdefaultgateway(in_addr_t *addr) break; } intfSize = sizeof(route) + IF_NAMESIZE; - if (route.destination != NULL) { + if (route.destination != nullptr) { intfSize += route.destination->sa_len; } - if (route.mask != NULL) { + if (route.mask != nullptr) { intfSize += route.mask->sa_len; } - if (route.gateway != NULL) { + if (route.gateway != nullptr) { intfSize += route.gateway->sa_len; } interface = (struct ifreq *)((uint8_t *)interface + intfSize); diff --git a/src/natpmp/natpmp.c b/src/natpmp/natpmp.c index 6cb1d3c0db794..f0459500fe939 100644 --- a/src/natpmp/natpmp.c +++ b/src/natpmp/natpmp.c @@ -131,7 +131,7 @@ int sendnatpmprequest(natpmp_t * p) p->has_pending_request = 1; p->try_number = 1; n = sendpendingrequest(p); - gettimeofday(&p->retry_time, NULL); // check errors ! + gettimeofday(&p->retry_time, nullptr); // check errors ! p->retry_time.tv_usec += 250000; /* add 250ms */ if(p->retry_time.tv_usec >= 1000000) { p->retry_time.tv_usec -= 1000000; @@ -147,7 +147,7 @@ NATPMP_LIBSPEC int getnatpmprequesttimeout(natpmp_t * p, struct timeval * timeou return NATPMP_ERR_INVALIDARGS; if(!p->has_pending_request) return NATPMP_ERR_NOPENDINGREQ; - if(gettimeofday(&now, NULL) < 0) + if(gettimeofday(&now, nullptr) < 0) return NATPMP_ERR_GETTIMEOFDAYERR; timeout->tv_sec = p->retry_time.tv_sec - now.tv_sec; timeout->tv_usec = p->retry_time.tv_usec - now.tv_usec; @@ -280,7 +280,7 @@ NATPMP_LIBSPEC int readnatpmpresponseorretry(natpmp_t * p, natpmpresp_t * respon if(n<0) { if(n==NATPMP_TRYAGAIN) { struct timeval now; - gettimeofday(&now, NULL); // check errors ! + gettimeofday(&now, nullptr); // check errors ! if(timercmp(&now, &p->retry_time, >=)) { int delay, r; if(p->try_number >= 9) { diff --git a/src/natpmp/natpmp_declspec.h b/src/natpmp/natpmp_declspec.h new file mode 100644 index 0000000000000..1d8c8d31d83f6 --- /dev/null +++ b/src/natpmp/natpmp_declspec.h @@ -0,0 +1,21 @@ +#ifndef DECLSPEC_H_INCLUDED +#define DECLSPEC_H_INCLUDED + +#if defined(WIN32) && !defined(NATPMP_STATICLIB) + /* for windows dll */ + #ifdef NATPMP_EXPORTS + #define NATPMP_LIBSPEC __declspec(dllexport) + #else + #define NATPMP_LIBSPEC __declspec(dllimport) + #endif +#else + #if defined(__GNUC__) && __GNUC__ >= 4 + /* fix dynlib for OS X 10.9.2 and Apple LLVM version 5.0 */ + #define NATPMP_LIBSPEC __attribute__ ((visibility ("default"))) + #else + #define NATPMP_LIBSPEC + #endif +#endif + +#endif + From e42be344119954e266f7324f37fad0c28781de6a Mon Sep 17 00:00:00 2001 From: Annanay Date: Sat, 10 Mar 2018 01:49:37 +0530 Subject: [PATCH 06/17] Add natpmp/natpmp_declspec.h to Makefile.am --- src/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Makefile.am b/src/Makefile.am index aa412c4a5607d..20b6eafb77f74 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -113,6 +113,7 @@ BITCOIN_CORE_H = \ merkleblock.h \ miner.h \ natpmp/natpmp.h \ + natpmp/natpmp_declspec.h \ net.h \ net_processing.h \ netaddress.h \ From 883ff1113415fc73b80edd45397fc810695b7d12 Mon Sep 17 00:00:00 2001 From: Annanay Date: Sat, 10 Mar 2018 12:50:52 +0530 Subject: [PATCH 07/17] Fix headers --- src/natpmp/getgateway.c | 2 +- src/natpmp/natpmp.c | 6 +++--- src/natpmp/natpmp.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/natpmp/getgateway.c b/src/natpmp/getgateway.c index e073a31f218c1..45393f2e503d4 100644 --- a/src/natpmp/getgateway.c +++ b/src/natpmp/getgateway.c @@ -117,7 +117,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #endif -#include +#include #ifndef _WIN32 #define SUCCESS (0) diff --git a/src/natpmp/natpmp.c b/src/natpmp/natpmp.c index f0459500fe939..03c824681ce1a 100644 --- a/src/natpmp/natpmp.c +++ b/src/natpmp/natpmp.c @@ -43,7 +43,7 @@ POSSIBILITY OF SUCH DAMAGE. #ifndef ECONNREFUSED #define ECONNREFUSED WSAECONNREFUSED #endif -#include +#include #define gettimeofday natpmp_gettimeofday #else #include @@ -53,8 +53,8 @@ POSSIBILITY OF SUCH DAMAGE. #include #define closesocket close #endif -#include -#include +#include +#include #include NATPMP_LIBSPEC int initnatpmp(natpmp_t * p, int forcegw, in_addr_t forcedgw) diff --git a/src/natpmp/natpmp.h b/src/natpmp/natpmp.h index 97bfb0eef2a6b..280ac3671faf3 100644 --- a/src/natpmp/natpmp.h +++ b/src/natpmp/natpmp.h @@ -46,7 +46,7 @@ typedef unsigned short uint16_t; #include #endif -#include +#include typedef struct { int s; /* socket */ From 2e8c84f18c0b906badaf5f6b22bcf4f6fd5fb129 Mon Sep 17 00:00:00 2001 From: Annanay Date: Sat, 10 Mar 2018 13:34:56 +0530 Subject: [PATCH 08/17] Updated StartMapPort() --- src/net.cpp | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 9d6028a1e1d7b..41f7e38464641 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1475,8 +1475,8 @@ void ThreadMapPort() fd_set fds; int i; int protocol = 0; - uint16_t privateport = std::atoi(port); - uint16_t publicport = std::atoi(port); + uint16_t privateport = std::atoi(port.c_str()); + uint16_t publicport = std::atoi(port.c_str()); uint32_t lifetime = 3600; int command = 0; int forcegw = 0; @@ -1566,20 +1566,9 @@ void ThreadMapPort() void StartMapPort() { - static std::unique_ptr natpmp_thread; - - if (fUseUPnP) - { - if (natpmp_thread) { - natpmp_thread->interrupt(); - natpmp_thread->join(); - } - natpmp_thread.reset(new boost::thread(boost::bind(&TraceThread, "upnp", &ThreadMapPort))); - } - else if (natpmp_thread) { - natpmp_thread->interrupt(); - natpmp_thread->join(); - natpmp_thread.reset(); + if (!g_upnp_thread.joinable()) { + assert(!g_upnp_interrupt); + g_upnp_thread = std::thread((std::bind(&TraceThread, "upnp", &ThreadMapPort))); } } From c663b6f0675fb4820035c47077771c5dfe5b8530 Mon Sep 17 00:00:00 2001 From: Annanay Date: Sat, 10 Mar 2018 18:39:01 +0530 Subject: [PATCH 09/17] Fixed net.cpp errors --- src/net.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/net.cpp b/src/net.cpp index 41f7e38464641..c52019ba2a90d 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1572,6 +1572,21 @@ void StartMapPort() } } +void InterruptMapPort() +{ + if(g_upnp_thread.joinable()) { + g_upnp_interrupt(); + } +} + +void StopMapPort() +{ + if(g_upnp_thread.joinable()) { + g_upnp_thread.join(); + g_upnp_interrupt.reset(); + } +} + #else void StartMapPort() { From ec5158c00e9ce21c19482f31e290f6fc755e9ce1 Mon Sep 17 00:00:00 2001 From: Annanay Date: Sat, 10 Mar 2018 19:51:47 +0530 Subject: [PATCH 10/17] Added dependency files --- src/Makefile.am | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Makefile.am b/src/Makefile.am index 20b6eafb77f74..a5c52ca50bb61 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -205,6 +205,9 @@ libbitcoin_server_a_SOURCES = \ merkleblock.cpp \ miner.cpp \ net.cpp \ + natpmp/natpmp.c \ + natpmp/getgateway.c \ + natpmp/wingettimeofday.c \ net_processing.cpp \ noui.cpp \ policy/fees.cpp \ From 3e70af696e9c11f58165358b1db3ae04025af3b7 Mon Sep 17 00:00:00 2001 From: Annanay Date: Sun, 11 Mar 2018 19:05:25 +0530 Subject: [PATCH 11/17] Some changes to work with NATPMP API --- src/natpmp/natpmp.c | 11 ++++++----- src/natpmp/natpmp.h | 2 +- src/net.cpp | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/natpmp/natpmp.c b/src/natpmp/natpmp.c index 03c824681ce1a..8ca58fd0539f6 100644 --- a/src/natpmp/natpmp.c +++ b/src/natpmp/natpmp.c @@ -56,8 +56,9 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include -NATPMP_LIBSPEC int initnatpmp(natpmp_t * p, int forcegw, in_addr_t forcedgw) +NATPMP_LIBSPEC int initnatpmp(natpmp_t * p, int forcegw, in_addr_t forcedgw, const char *port) { #ifdef WIN32 u_long ioctlArg = 1; @@ -90,7 +91,7 @@ NATPMP_LIBSPEC int initnatpmp(natpmp_t * p, int forcegw, in_addr_t forcedgw) memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; - addr.sin_port = htons(NATPMP_PORT); + addr.sin_port = port; addr.sin_addr.s_addr = p->gateway; if(connect(p->s, (struct sockaddr *)&addr, sizeof(addr)) < 0) return NATPMP_ERR_CONNECTERR; @@ -131,7 +132,7 @@ int sendnatpmprequest(natpmp_t * p) p->has_pending_request = 1; p->try_number = 1; n = sendpendingrequest(p); - gettimeofday(&p->retry_time, nullptr); // check errors ! + gettimeofday(&p->retry_time, NULL); // check errors ! p->retry_time.tv_usec += 250000; /* add 250ms */ if(p->retry_time.tv_usec >= 1000000) { p->retry_time.tv_usec -= 1000000; @@ -147,7 +148,7 @@ NATPMP_LIBSPEC int getnatpmprequesttimeout(natpmp_t * p, struct timeval * timeou return NATPMP_ERR_INVALIDARGS; if(!p->has_pending_request) return NATPMP_ERR_NOPENDINGREQ; - if(gettimeofday(&now, nullptr) < 0) + if(gettimeofday(&now, NULL) < 0) return NATPMP_ERR_GETTIMEOFDAYERR; timeout->tv_sec = p->retry_time.tv_sec - now.tv_sec; timeout->tv_usec = p->retry_time.tv_usec - now.tv_usec; @@ -280,7 +281,7 @@ NATPMP_LIBSPEC int readnatpmpresponseorretry(natpmp_t * p, natpmpresp_t * respon if(n<0) { if(n==NATPMP_TRYAGAIN) { struct timeval now; - gettimeofday(&now, nullptr); // check errors ! + gettimeofday(&now, NULL); // check errors ! if(timercmp(&now, &p->retry_time, >=)) { int delay, r; if(p->try_number >= 9) { diff --git a/src/natpmp/natpmp.h b/src/natpmp/natpmp.h index 280ac3671faf3..3e0c95df2125b 100644 --- a/src/natpmp/natpmp.h +++ b/src/natpmp/natpmp.h @@ -134,7 +134,7 @@ extern "C" { * NATPMP_ERR_FCNTLERROR * NATPMP_ERR_CANNOTGETGATEWAY * NATPMP_ERR_CONNECTERR */ -NATPMP_LIBSPEC int initnatpmp(natpmp_t * p, int forcegw, in_addr_t forcedgw); +NATPMP_LIBSPEC int initnatpmp(natpmp_t * p, int forcegw, in_addr_t forcedgw, const char *port); /* closenatpmp() * close resources associated with a natpmp_t object diff --git a/src/net.cpp b/src/net.cpp index c52019ba2a90d..41bb35c5d7200 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1486,7 +1486,7 @@ void ThreadMapPort() try{ /* initnatpmp() */ - r = initnatpmp(&natpmp, forcegw, gateway); + r = initnatpmp(&natpmp, forcegw, gateway, port.c_str()); LogPrintf("NATPMP: initnatpmp returned %d\n", r); gateway_in_use.s_addr = natpmp.gateway; From 14547d17ef058edbf8c6e6fa95e2c925a94c4118 Mon Sep 17 00:00:00 2001 From: Annanay Date: Tue, 13 Mar 2018 10:32:11 +0530 Subject: [PATCH 12/17] Fix includes --- src/natpmp/getgateway.c | 2 +- src/natpmp/natpmp.c | 6 +++--- src/natpmp/natpmp.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/natpmp/getgateway.c b/src/natpmp/getgateway.c index 45393f2e503d4..0128fd42344ff 100644 --- a/src/natpmp/getgateway.c +++ b/src/natpmp/getgateway.c @@ -117,7 +117,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #endif -#include +#include "getgateway.h" #ifndef _WIN32 #define SUCCESS (0) diff --git a/src/natpmp/natpmp.c b/src/natpmp/natpmp.c index 8ca58fd0539f6..98871a4424fdb 100644 --- a/src/natpmp/natpmp.c +++ b/src/natpmp/natpmp.c @@ -43,7 +43,7 @@ POSSIBILITY OF SUCH DAMAGE. #ifndef ECONNREFUSED #define ECONNREFUSED WSAECONNREFUSED #endif -#include +#include "wingettimeofday.h" #define gettimeofday natpmp_gettimeofday #else #include @@ -53,8 +53,8 @@ POSSIBILITY OF SUCH DAMAGE. #include #define closesocket close #endif -#include -#include +#include "natpmp.h" +#include "getgateway.h" #include #include diff --git a/src/natpmp/natpmp.h b/src/natpmp/natpmp.h index 3e0c95df2125b..4013aca602833 100644 --- a/src/natpmp/natpmp.h +++ b/src/natpmp/natpmp.h @@ -46,7 +46,7 @@ typedef unsigned short uint16_t; #include #endif -#include +#include "natpmp_declspec.h" typedef struct { int s; /* socket */ From 74dc8f73fb81c3c0e770768dd31d8bb28cbddc65 Mon Sep 17 00:00:00 2001 From: Annanay Date: Tue, 13 Mar 2018 10:51:59 +0530 Subject: [PATCH 13/17] Fix includes again --- src/natpmp/getgateway.c | 2 +- src/natpmp/natpmp.c | 6 +++--- src/natpmp/natpmp.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/natpmp/getgateway.c b/src/natpmp/getgateway.c index 0128fd42344ff..e073a31f218c1 100644 --- a/src/natpmp/getgateway.c +++ b/src/natpmp/getgateway.c @@ -117,7 +117,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #endif -#include "getgateway.h" +#include #ifndef _WIN32 #define SUCCESS (0) diff --git a/src/natpmp/natpmp.c b/src/natpmp/natpmp.c index 98871a4424fdb..e466cbcbdced4 100644 --- a/src/natpmp/natpmp.c +++ b/src/natpmp/natpmp.c @@ -43,7 +43,7 @@ POSSIBILITY OF SUCH DAMAGE. #ifndef ECONNREFUSED #define ECONNREFUSED WSAECONNREFUSED #endif -#include "wingettimeofday.h" +#include #define gettimeofday natpmp_gettimeofday #else #include @@ -53,8 +53,8 @@ POSSIBILITY OF SUCH DAMAGE. #include #define closesocket close #endif -#include "natpmp.h" -#include "getgateway.h" +#include +#include #include #include diff --git a/src/natpmp/natpmp.h b/src/natpmp/natpmp.h index 4013aca602833..ccb80ebf82676 100644 --- a/src/natpmp/natpmp.h +++ b/src/natpmp/natpmp.h @@ -46,7 +46,7 @@ typedef unsigned short uint16_t; #include #endif -#include "natpmp_declspec.h" +#include typedef struct { int s; /* socket */ From e1ca3303201bb63a877cd480e7357808b227bb48 Mon Sep 17 00:00:00 2001 From: Annanay Date: Tue, 13 Mar 2018 12:24:38 +0530 Subject: [PATCH 14/17] Added more headers to Makefile --- src/natpmp/getgateway.c | 2 +- src/natpmp/natpmp.c | 6 +++--- src/natpmp/natpmp.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/natpmp/getgateway.c b/src/natpmp/getgateway.c index e073a31f218c1..45393f2e503d4 100644 --- a/src/natpmp/getgateway.c +++ b/src/natpmp/getgateway.c @@ -117,7 +117,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #endif -#include +#include #ifndef _WIN32 #define SUCCESS (0) diff --git a/src/natpmp/natpmp.c b/src/natpmp/natpmp.c index e466cbcbdced4..8ca58fd0539f6 100644 --- a/src/natpmp/natpmp.c +++ b/src/natpmp/natpmp.c @@ -43,7 +43,7 @@ POSSIBILITY OF SUCH DAMAGE. #ifndef ECONNREFUSED #define ECONNREFUSED WSAECONNREFUSED #endif -#include +#include #define gettimeofday natpmp_gettimeofday #else #include @@ -53,8 +53,8 @@ POSSIBILITY OF SUCH DAMAGE. #include #define closesocket close #endif -#include -#include +#include +#include #include #include diff --git a/src/natpmp/natpmp.h b/src/natpmp/natpmp.h index ccb80ebf82676..3e0c95df2125b 100644 --- a/src/natpmp/natpmp.h +++ b/src/natpmp/natpmp.h @@ -46,7 +46,7 @@ typedef unsigned short uint16_t; #include #endif -#include +#include typedef struct { int s; /* socket */ From fd6eae66d87546f991149aef87ff810fbc893694 Mon Sep 17 00:00:00 2001 From: Annanay Date: Tue, 13 Mar 2018 12:35:35 +0530 Subject: [PATCH 15/17] Added more headers to Makefile --- src/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Makefile.am b/src/Makefile.am index a5c52ca50bb61..bfec1e447ed55 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -112,8 +112,10 @@ BITCOIN_CORE_H = \ memusage.h \ merkleblock.h \ miner.h \ + natpmp/getgateway.h \ natpmp/natpmp.h \ natpmp/natpmp_declspec.h \ + natpmp/wingettimeofday.h \ net.h \ net_processing.h \ netaddress.h \ From a9c9b10cf40410dcb22177640e1ef78a83c01342 Mon Sep 17 00:00:00 2001 From: Annanay Date: Fri, 23 Mar 2018 12:21:31 +0530 Subject: [PATCH 16/17] Add atoi for port mapping --- src/natpmp/natpmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/natpmp/natpmp.c b/src/natpmp/natpmp.c index 8ca58fd0539f6..5b7ae202d033b 100644 --- a/src/natpmp/natpmp.c +++ b/src/natpmp/natpmp.c @@ -91,7 +91,7 @@ NATPMP_LIBSPEC int initnatpmp(natpmp_t * p, int forcegw, in_addr_t forcedgw, con memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; - addr.sin_port = port; + addr.sin_port = atoi(port); addr.sin_addr.s_addr = p->gateway; if(connect(p->s, (struct sockaddr *)&addr, sizeof(addr)) < 0) return NATPMP_ERR_CONNECTERR; From fcd026b8e0313a7a46e29ddca8e97274e97b08ae Mon Sep 17 00:00:00 2001 From: Annanay Date: Wed, 11 Apr 2018 16:29:07 +0530 Subject: [PATCH 17/17] Fix extern C in header files --- src/natpmp/getgateway.h | 8 ++++++++ src/natpmp/wingettimeofday.h | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/src/natpmp/getgateway.h b/src/natpmp/getgateway.h index 90322a366e057..a06578c7105f0 100644 --- a/src/natpmp/getgateway.h +++ b/src/natpmp/getgateway.h @@ -37,6 +37,10 @@ typedef unsigned short uint16_t; #endif /* #include "declspec.h" */ +#ifdef __cplusplus +extern "C" { +#endif + /* getdefaultgateway() : * return value : * 0 : success @@ -44,4 +48,8 @@ typedef unsigned short uint16_t; /* NATPMP_LIBSPEC */ int getdefaultgateway(in_addr_t * addr); +#ifdef __cplusplus +} +#endif + #endif diff --git a/src/natpmp/wingettimeofday.h b/src/natpmp/wingettimeofday.h index 577b7f5369263..48acc4079ed40 100644 --- a/src/natpmp/wingettimeofday.h +++ b/src/natpmp/wingettimeofday.h @@ -31,6 +31,14 @@ POSSIBILITY OF SUCH DAMAGE. #else #include #endif + +#ifdef __cplusplus +extern "C" { +#endif int natpmp_gettimeofday(struct timeval* p, void* tz /* IGNORED */); +#ifdef __cplusplus +} +#endif + #endif #endif