mirror of
https://github.com/ntop/n2n.git
synced 2024-11-01 05:07:57 +05:30
added port forwarding (upnp and natpmp) (#905)
* UPnP port redirection is supported. * compile fixes * compile fix * optimize reconnection code * prepared upnp threadification to counter main loop stall at supernode change * NAT-PMP port forwarding support, temporarily merge codes to resolve conflicts. * make compile fix * prepared threadification in more detail * adopted threadification to new file setup * cleaned up * renamed functions and data structures * fixes * differentiated between miniupnp and natpmp and added corresponding lib support to makefile * name * commented unused header includes * comments * license * fixes * fixes * fixes * NAT-PMP is already available. * added CLI parameter to disable port forwarding if required * preliminary made use of multithreading * adjusted log level * added man page documentation * def'ed conf * made pmpnat adjustments Co-authored-by: fengdaolong <fengdaolong@gmail.com>
This commit is contained in:
parent
a1facf0f3f
commit
e6e8cb038a
1
.gitignore
vendored
1
.gitignore
vendored
@ -16,6 +16,7 @@ tools/n2n-decode
|
||||
tools/n2n-keygen
|
||||
build
|
||||
.idea
|
||||
.vscode
|
||||
cmake-build-default
|
||||
packages/debian/debian/changelog
|
||||
packages/debian/debian/control
|
||||
|
8
.gitmodules
vendored
Normal file
8
.gitmodules
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
[submodule "thirdparty/miniupnp"]
|
||||
path = thirdparty/miniupnp
|
||||
url = https://github.com/miniupnp/miniupnp.git
|
||||
ignore = dirty
|
||||
[submodule "thirdparty/libnatpmp"]
|
||||
path = thirdparty/libnatpmp
|
||||
url = https://github.com/miniupnp/libnatpmp.git
|
||||
ignore = dirty
|
@ -30,6 +30,8 @@ add_definitions(-DCMAKE_BUILD)
|
||||
add_definitions(-DPACKAGE_OSNAME="${CMAKE_SYSTEM_NAME}")
|
||||
add_definitions(-DPACKAGE_VERSION="${PACKAGE_VERSION}")
|
||||
|
||||
# third-party directory
|
||||
set(THIRD_PARTY_DIR ${CMAKE_SOURCE_DIR}/thirdparty)
|
||||
|
||||
# Build information
|
||||
OPTION(BUILD_SHARED_LIBS "BUILD Shared Library" OFF)
|
||||
@ -39,6 +41,7 @@ OPTION(N2N_OPTION_USE_PTHREAD "USE PTHREAD Library" ON)
|
||||
OPTION(N2N_OPTION_USE_OPENSSL "USE OPENSSL Library" OFF)
|
||||
OPTION(N2N_OPTION_USE_PCAPLIB "USE PCAP Library" OFF)
|
||||
OPTION(N2N_OPTION_USE_ZSTD "USE ZSTD Library" OFF)
|
||||
OPTION(N2N_OPTION_USE_PORTMAPPING "USE MINIUPNP and NATPMP Libraries" ON)
|
||||
|
||||
|
||||
if(N2N_OPTION_USE_PTHREAD)
|
||||
@ -47,7 +50,7 @@ if(N2N_OPTION_USE_PTHREAD)
|
||||
ADD_DEFINITIONS("-DHAVE_PTHREAD")
|
||||
else()
|
||||
MESSAGE(WARNING "libpthread not found.")
|
||||
set(N2N_OPTION_USE_PTHREAD OFF)
|
||||
set(N2N_OPTION_USE_PTHREAD OFF)
|
||||
endif(PTHREAD_LIB)
|
||||
endif(N2N_OPTION_USE_PTHREAD)
|
||||
|
||||
@ -75,6 +78,14 @@ if(N2N_OPTION_USE_ZSTD)
|
||||
add_definitions(-DN2N_HAVE_ZSTD)
|
||||
endif(N2N_OPTION_USE_ZSTD)
|
||||
|
||||
if(N2N_OPTION_USE_PORTMAPPING)
|
||||
ADD_DEFINITIONS("-DHAVE_MINIUPNP")
|
||||
ADD_DEFINITIONS("-DHAVE_NATPMP")
|
||||
include_directories(${THIRD_PARTY_DIR}/miniupnp/miniupnpc/include)
|
||||
include_directories(${PROJECT_BINARY_DIR}/lib_miniupnpc)
|
||||
include_directories(${THIRD_PARTY_DIR}/libnatpmp)
|
||||
endif(N2N_OPTION_USE_PORTMAPPING)
|
||||
|
||||
if(NOT DEFINED CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE None)
|
||||
endif(NOT DEFINED CMAKE_BUILD_TYPE)
|
||||
@ -85,7 +96,7 @@ if (DEFINED UNIX)
|
||||
# None
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wshadow -Wpointer-arith -Wmissing-declarations -Wnested-externs")
|
||||
set(CMAKE_CXX_FLAGS "-Wall -Wshadow -Wpointer-arith -Wmissing-declarations -Wnested-externs")
|
||||
# Debug
|
||||
# Debug
|
||||
set(CMAKE_C_FLAGS_DEBUG "-g")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-g")
|
||||
# Release
|
||||
@ -139,7 +150,8 @@ add_library(n2n STATIC
|
||||
src/network_traffic_filter.c
|
||||
src/sn_selection.c
|
||||
src/auth.c
|
||||
src/curve25519.c)
|
||||
src/curve25519.c
|
||||
src/n2n_port_mapping.c)
|
||||
|
||||
|
||||
if(N2N_OPTION_USE_PTHREAD)
|
||||
@ -155,6 +167,14 @@ if(N2N_OPTION_USE_ZSTD)
|
||||
target_link_libraries(n2n zstd)
|
||||
endif(N2N_OPTION_USE_ZSTD)
|
||||
|
||||
if(N2N_OPTION_USE_PORTMAPPING)
|
||||
add_subdirectory(${THIRD_PARTY_DIR}/miniupnp/miniupnpc lib_miniupnpc)
|
||||
link_directories(${PROJECT_BINARY_DIR}/lib_miniupnpc)
|
||||
add_subdirectory(${THIRD_PARTY_DIR}/libnatpmp libnatpmp)
|
||||
link_directories(${PROJECT_BINARY_DIR}/libnatpmp)
|
||||
target_link_libraries(n2n libminiupnpc-static natpmp)
|
||||
endif(N2N_OPTION_USE_PORTMAPPING)
|
||||
|
||||
if(DEFINED WIN32)
|
||||
add_library(edge_utils_win32 src/edge_utils_win32.c)
|
||||
add_subdirectory(win32)
|
||||
|
14
configure.ac
14
configure.ac
@ -58,6 +58,20 @@ if test "x$with_openssl" != xno; then
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_CHECK_LIB([miniupnpc], [upnpDiscover], miniupnp=true)
|
||||
|
||||
if test x$miniupnp != x; then
|
||||
AC_DEFINE([HAVE_MINIUPNP], [], [Have miniupnp library])
|
||||
N2N_LIBS="-lminiupnpc ${N2N_LIBS}"
|
||||
fi
|
||||
|
||||
AC_CHECK_LIB([natpmp], [initnatpmp], natpmp=true)
|
||||
|
||||
if test x$natpmp != x; then
|
||||
AC_DEFINE([HAVE_NATPMP], [], [Have natpmp library])
|
||||
N2N_LIBS="-lnatpmp ${N2N_LIBS}"
|
||||
fi
|
||||
|
||||
AC_CHECK_LIB([pcap], [pcap_open_live], pcap=true)
|
||||
|
||||
if test x$pcap != x; then
|
||||
|
7
edge.8
7
edge.8
@ -109,6 +109,11 @@ defaults to load-based selection strategy if not provided.
|
||||
\fB\-\-select-mac\fR
|
||||
select supernode by MAC address if several to choose from (federation),
|
||||
lowest MAC address first.
|
||||
.TP
|
||||
\fB\-\-no-port-forwarding\fR
|
||||
disables the default behavior of trying to have the edge's port forwarded
|
||||
through a router eventually supporting it (only if compiled with miniupnp
|
||||
and/or natpmp library support).
|
||||
.SH TAP DEVICE AND OVERLAY NETWORK CONFIGURATION
|
||||
.TP
|
||||
\fB\-a \fR[\fImode\fR]<\fIip\fR>[\fI/n\fR]
|
||||
@ -245,7 +250,7 @@ The MAC address (-m <MAC>) and virtual IP address (-a <addr>) must be different
|
||||
on all edges in the same community.
|
||||
|
||||
.SH CLEARTEXT MODE
|
||||
If
|
||||
If
|
||||
.B -k
|
||||
is not specified then edge uses cleartext mode. In cleartext mode there is no
|
||||
transform of the packet data it is simply encrypted. This is useful for
|
||||
|
@ -158,6 +158,10 @@
|
||||
#include "network_traffic_filter.h"
|
||||
#include "auth.h"
|
||||
|
||||
#if defined(HAVE_MINIUPNP) || defined(HAVE_NATPMP)
|
||||
#include "n2n_port_mapping.h"
|
||||
#endif // HAVE_MINIUPNP || HAVE_NATPMP
|
||||
|
||||
/* ************************************** */
|
||||
|
||||
#include "header_encryption.h"
|
||||
|
21
include/n2n_port_mapping.h
Normal file
21
include/n2n_port_mapping.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef _N2N_PORT_MAPPING_H_
|
||||
#define _N2N_PORT_MAPPING_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef HAVE_MINIUPNP
|
||||
#include <miniupnpc/miniupnpc.h>
|
||||
#include <miniupnpc/upnpcommands.h>
|
||||
#include <miniupnpc/upnperrors.h>
|
||||
#endif // HAVE_MINIUPNP
|
||||
|
||||
|
||||
#ifdef HAVE_NATPMP
|
||||
#include "natpmp.h"
|
||||
#endif // HAVE_NATPMP
|
||||
|
||||
|
||||
void n2n_chg_port_mapping (struct n2n_edge *eee, const uint16_t port);
|
||||
|
||||
|
||||
#endif // _N2N_PORT_MAPPING_H_
|
@ -637,6 +637,21 @@ typedef struct n2n_resolve_parameter {
|
||||
/* *************************************************** */
|
||||
|
||||
|
||||
// structure to hold port mapping thread's parameters
|
||||
typedef struct n2n_port_map_parameter {
|
||||
#ifdef HAVE_PTHREAD
|
||||
pthread_t id; /* thread id */
|
||||
pthread_mutex_t access; /* mutex for shared access */
|
||||
#endif
|
||||
uint16_t mgmt_port;
|
||||
uint16_t mapped_port;
|
||||
uint16_t new_port; /* REVISIT: remove with management port subscriptions */
|
||||
} n2n_port_map_parameter_t;
|
||||
|
||||
|
||||
/* *************************************************** */
|
||||
|
||||
|
||||
typedef struct n2n_edge_conf {
|
||||
struct peer_info *supernodes; /**< List of supernodes */
|
||||
n2n_route_t *routes; /**< Networks to route through n2n */
|
||||
@ -676,6 +691,7 @@ typedef struct n2n_edge_conf {
|
||||
uint8_t sn_selection_strategy; /**< encodes currently chosen supernode selection strategy. */
|
||||
uint8_t number_max_sn_pings; /**< Number of maximum concurrently allowed supernode pings. */
|
||||
uint64_t mgmt_password_hash; /**< contains hash of managament port password. */
|
||||
uint8_t port_forwarding; /**< indicates if port forwarding UPNP/PMP is enabled */
|
||||
} n2n_edge_conf_t;
|
||||
|
||||
|
||||
@ -733,6 +749,8 @@ struct n2n_edge {
|
||||
n2n_resolve_parameter_t *resolve_parameter; /**< Pointer to name resolver's parameter block */
|
||||
uint8_t resolution_request; /**< Flag an immediate DNS resolution request */
|
||||
|
||||
n2n_port_map_parameter_t *port_map_parameter; /**< Pointer to port mapping thread's parameter block */
|
||||
|
||||
n2n_tuntap_priv_config_t tuntap_priv_conf; /**< Tuntap config */
|
||||
|
||||
network_traffic_filter_t *network_traffic_filter;
|
||||
|
19
src/edge.c
19
src/edge.c
@ -180,7 +180,10 @@ static void help (int level) {
|
||||
"\n "
|
||||
"[-e <preferred local IP address>] [-S<level of solitude>]"
|
||||
"\n "
|
||||
"[--select-rtt]"
|
||||
"[--select-rtt] "
|
||||
#if defined(HAVE_MINIUPNP) || defined(HAVE_NATPMP)
|
||||
"[--no-port-forwarding] "
|
||||
#endif // HAVE_MINIUPNP || HAVE_NATPMP
|
||||
"\n\n tap device and "
|
||||
"[-a [static:|dhcp:]<tap IP address>[/<cidr suffix>]] "
|
||||
"\n overlay network "
|
||||
@ -233,6 +236,9 @@ static void help (int level) {
|
||||
"\n [-E] accept multicast MAC addresses"
|
||||
"\n [--select-rtt] select supernode by round trip time"
|
||||
"\n [--select-mac] select supernode by MAC address"
|
||||
#if defined(HAVE_MINIUPNP) || defined(HAVE_NATPMP)
|
||||
"\n [--no-port-forwarding] disable UPnP/PMP port forwarding"
|
||||
#endif // HAVE_MINIUPNP || HAVE_NATPMP
|
||||
#ifndef WIN32
|
||||
"\n [-f] do not fork but run in foreground"
|
||||
#endif
|
||||
@ -294,6 +300,10 @@ static void help (int level) {
|
||||
printf("--select-rtt | supernode selection based on round trip time\n"
|
||||
"--select-mac | supernode selection based on MAC address (default:\n"
|
||||
" | by load)\n");
|
||||
#if defined(HAVE_MINIUPNP) || defined(HAVE_NATPMP)
|
||||
printf("--no-port-... | disable UPnP/PMP port forwarding\n"
|
||||
"...forwarding | \n");
|
||||
#endif // HAVE_MINIUPNP || HAVE_NATPMP
|
||||
|
||||
printf ("\n");
|
||||
printf (" TAP DEVICE AND OVERLAY NETWORK CONFIGURATION\n");
|
||||
@ -752,6 +762,12 @@ static int setOption (int optkey, char *optargument, n2n_tuntap_priv_config_t *e
|
||||
break;
|
||||
}
|
||||
|
||||
case '}': /* disable port forwarding */ {
|
||||
conf->port_forwarding = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'h': /* quick reference */ {
|
||||
return 2;
|
||||
}
|
||||
@ -808,6 +824,7 @@ static const struct option long_options[] =
|
||||
{ "select-rtt", no_argument, NULL, '[' }, /* '[' rtt selection strategy */
|
||||
{ "select-mac", no_argument, NULL, ']' }, /* ']' mac selection strategy */
|
||||
{ "management-password", required_argument, NULL, '{' }, /* '{' management port password */
|
||||
{ "no-port-forwarding", no_argument, NULL, '}' }, /* '}' disable port forwarding */
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -30,6 +30,9 @@ int resolve_create_thread (n2n_resolve_parameter_t **param, struct peer_info *sn
|
||||
int resolve_check (n2n_resolve_parameter_t *param, uint8_t resolution_request, time_t now);
|
||||
int resolve_cancel_thread (n2n_resolve_parameter_t *param);
|
||||
|
||||
int port_map_create_thread (n2n_port_map_parameter_t **param, uint16_t mgmt_port);
|
||||
int port_map_cancel_thread (n2n_port_map_parameter_t *param);
|
||||
|
||||
static const char * supernode_ip (const n2n_edge_t * eee);
|
||||
static void send_register (n2n_edge_t *eee, const n2n_sock_t *remote_peer, const n2n_mac_t peer_mac, n2n_cookie_t cookie);
|
||||
|
||||
@ -329,6 +332,12 @@ int supernode_connect (n2n_edge_t *eee) {
|
||||
eee->cb.sock_opened(eee);
|
||||
}
|
||||
|
||||
#if defined(HAVE_MINIUPNP) || defined(HAVE_NATPMP)
|
||||
if(eee->conf.port_forwarding)
|
||||
// REVISIT: replace with mgmt port notification to listener for mgmt port
|
||||
// subscription support
|
||||
n2n_chg_port_mapping(eee, eee->conf.preferred_sock.port);
|
||||
#endif // HAVE_MINIUPNP || HAVE_NATPMP
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -482,7 +491,12 @@ n2n_edge_t* edge_init (const n2n_edge_conf_t *conf, int *rv) {
|
||||
if(resolve_create_thread(&(eee->resolve_parameter), eee->conf.supernodes) == 0) {
|
||||
traceEvent(TRACE_NORMAL, "successfully created resolver thread");
|
||||
}
|
||||
|
||||
#if defined(HAVE_MINIUPNP) || defined(HAVE_NATPMP)
|
||||
if(eee->conf.port_forwarding)
|
||||
if(port_map_create_thread(&eee->port_map_parameter, eee->conf.mgmt_port) == 0) {
|
||||
traceEvent(TRACE_NORMAL, "successfully created port mapping thread");
|
||||
}
|
||||
#endif // HAVE_MINIUPNP || HAVE_NATPMP
|
||||
eee->network_traffic_filter = create_network_traffic_filter();
|
||||
network_traffic_filter_add_rule(eee->network_traffic_filter, eee->conf.network_traffic_filter_rules);
|
||||
|
||||
@ -1539,7 +1553,6 @@ void update_supernode_reg (n2n_edge_t * eee, time_t now) {
|
||||
sn_selection_sort(&(eee->conf.supernodes));
|
||||
eee->curr_sn = eee->conf.supernodes;
|
||||
traceEvent(TRACE_WARNING, "supernode not responding, now trying [%s]", supernode_ip(eee));
|
||||
supernode_connect(eee);
|
||||
reset_sup_attempts(eee);
|
||||
// trigger out-of-schedule DNS resolution
|
||||
eee->resolution_request = 1;
|
||||
@ -1567,9 +1580,9 @@ void update_supernode_reg (n2n_edge_t * eee, time_t now) {
|
||||
}
|
||||
}
|
||||
|
||||
supernode_connect(eee);
|
||||
traceEvent(TRACE_DEBUG, "reconnected to supernode");
|
||||
}
|
||||
supernode_connect(eee);
|
||||
|
||||
} else {
|
||||
--(eee->sup_attempts);
|
||||
@ -3182,9 +3195,9 @@ int run_edge_loop (n2n_edge_t *eee) {
|
||||
WaitForSingleObject(tun_read_thread, INFINITE);
|
||||
#endif
|
||||
|
||||
closesocket(eee->sock);
|
||||
supernode_disconnect(eee);
|
||||
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ************************************** */
|
||||
@ -3193,7 +3206,10 @@ int run_edge_loop (n2n_edge_t *eee) {
|
||||
void edge_term (n2n_edge_t * eee) {
|
||||
|
||||
resolve_cancel_thread(eee->resolve_parameter);
|
||||
|
||||
#if defined(HAVE_MINIUPNP) || defined(HAVE_NATPMP)
|
||||
if(eee->conf.port_forwarding)
|
||||
port_map_cancel_thread(eee->port_map_parameter);
|
||||
#endif // HAVE_MINIUPNP || HAVE_NATPMP
|
||||
if(eee->sock >= 0)
|
||||
closesocket(eee->sock);
|
||||
|
||||
@ -3712,6 +3728,10 @@ void edge_init_conf_defaults (n2n_edge_conf_t *conf) {
|
||||
free(tmp_string);
|
||||
}
|
||||
|
||||
#if defined(HAVE_MINIUPNP) || defined(HAVE_NATPMP)
|
||||
conf->port_forwarding = 1;
|
||||
#endif // HAVE_MINIUPNP || HAVE_NATPMP
|
||||
|
||||
conf->sn_selection_strategy = SN_SELECTION_STRATEGY_LOAD;
|
||||
conf->metric = 0;
|
||||
}
|
||||
|
635
src/n2n_port_mapping.c
Normal file
635
src/n2n_port_mapping.c
Normal file
@ -0,0 +1,635 @@
|
||||
/**
|
||||
* (C) 2007-21 - ntop.org and contributors
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not see see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// This file contains code taken from MiniUPnPc and natpmp found at
|
||||
// https://github.com/miniupnp/miniupnp/ or
|
||||
// https://github.com/miniupnp/natpmp/ respectively
|
||||
// both as of October 2021
|
||||
|
||||
|
||||
/**
|
||||
* MiniUPnPc
|
||||
* Copyright (c) 2005-2021, 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 "n2n.h"
|
||||
|
||||
|
||||
#ifdef HAVE_MINIUPNP
|
||||
|
||||
|
||||
#if 0 /* unused code */
|
||||
/* protofix() checks if protocol is "UDP" or "TCP"
|
||||
* returns NULL if not */
|
||||
static const char *protofix (const char *proto) {
|
||||
|
||||
int i, b;
|
||||
const char proto_tcp[4] = {'T', 'C', 'P', 0};
|
||||
const char proto_udp[4] = {'U', 'D', 'P', 0};
|
||||
|
||||
for(i = 0, b = 1; i < 4; i++)
|
||||
b = b && ((proto[i] == proto_tcp[i]) || (proto[i] == (proto_tcp[i] | 32)));
|
||||
if(b)
|
||||
return proto;
|
||||
for(i = 0, b = 1; i < 4; i++)
|
||||
b = b && ((proto[i] == proto_udp[i]) || (proto[i] == (proto_udp[i] | 32)));
|
||||
if(b)
|
||||
return proto;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif // unused code
|
||||
|
||||
|
||||
static int n2n_UPNP_GetValidIGD (struct UPNPUrls *urls, struct IGDdatas *data, char *lanaddr, char *externaladdr) {
|
||||
|
||||
struct UPNPDev *devlist = NULL;
|
||||
struct UPNPDev *device = NULL;
|
||||
int delay = 2000;
|
||||
const char *multicastif = NULL;
|
||||
const char *minissdpdpath = NULL;
|
||||
int localport = UPNP_LOCAL_PORT_ANY;
|
||||
int ipv6 = 0;
|
||||
unsigned char ttl = 2; /* defaulting to 2 */
|
||||
int error = 0;
|
||||
int ret = 0;
|
||||
|
||||
devlist = upnpDiscover(delay, multicastif, minissdpdpath, localport, ipv6, ttl, &error);
|
||||
if((error != UPNPDISCOVER_SUCCESS) || (devlist == NULL) ) {
|
||||
traceEvent(TRACE_WARNING, "no IGD UPnP device found on the network");
|
||||
return -1;
|
||||
}
|
||||
|
||||
traceEvent(TRACE_INFO, "list of UPnP devices found on the network:");
|
||||
for(device = devlist; device; device = device->pNext) {
|
||||
traceEvent(TRACE_INFO, " desc: %s", device->descURL);
|
||||
traceEvent(TRACE_INFO, " st: %s", device->st);
|
||||
traceEvent(TRACE_INFO, " usn: %s", device->usn);
|
||||
}
|
||||
|
||||
ret = UPNP_GetValidIGD(devlist, urls, data, lanaddr, N2N_NETMASK_STR_SIZE);
|
||||
if(ret == 0) {
|
||||
traceEvent(TRACE_WARNING, "UPnP get valid IGD failed, code %d (%s)", ret, strupnperror(ret));
|
||||
freeUPNPDevlist(devlist);
|
||||
devlist = NULL;
|
||||
return -1;
|
||||
}
|
||||
freeUPNPDevlist(devlist);
|
||||
devlist = NULL;
|
||||
traceEvent(TRACE_INFO, "UPnP found valid IGD: %s", urls->controlURL);
|
||||
|
||||
ret = UPNP_GetExternalIPAddress(urls->controlURL,
|
||||
data->first.servicetype,
|
||||
externaladdr);
|
||||
if(ret != UPNPCOMMAND_SUCCESS) {
|
||||
traceEvent(TRACE_WARNING, "UPnP get external ip address failed, code %d (%s)", ret, strupnperror(ret));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if 0 /* unused code */
|
||||
static int n2n_upnp_get_port_mapping (struct UPNPUrls *urls, const struct IGDdatas *data, const uint16_t port, const char *proto,
|
||||
char *lanaddr, char *lanport, char *description, char *enabled, char *duration) {
|
||||
|
||||
int errorcode = 0;
|
||||
// struct UPNPUrls urls;
|
||||
// struct IGDdatas data;
|
||||
// char lanaddr[N2N_NETMASK_STR_SIZE] = {'\0'};
|
||||
// char lanport[6] = {'\0'};
|
||||
// char externaladdr[N2N_NETMASK_STR_SIZE] = {'\0'};
|
||||
char externalport[6] = {'\0'};
|
||||
// char description[64] = {'\0'};
|
||||
// char enabled[16] = {'\0'};
|
||||
// char duration[16] = {'\0'};
|
||||
int ret = 0;
|
||||
|
||||
proto = protofix(proto);
|
||||
if(!proto) {
|
||||
traceEvent(TRACE_ERROR, "invalid protocol");
|
||||
errorcode = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
snprintf(externalport, sizeof(externalport), "%d", port);
|
||||
|
||||
ret = UPNP_GetSpecificPortMappingEntry(urls->controlURL,
|
||||
data->first.servicetype,
|
||||
externalport, proto, NULL,
|
||||
lanaddr, lanport, description,
|
||||
enabled, duration);
|
||||
if(ret != UPNPCOMMAND_SUCCESS) {
|
||||
traceEvent(TRACE_WARNING, "UPNP_GetSpecificPortMappingEntry() failed, code %d (%s)", ret, strupnperror(ret));
|
||||
errorcode = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
FreeUPNPUrls(urls);
|
||||
|
||||
return errorcode;
|
||||
}
|
||||
#endif // unused code
|
||||
|
||||
|
||||
static int n2n_upnp_set_port_mapping (const uint16_t port) {
|
||||
|
||||
int errorcode = 0;
|
||||
struct UPNPUrls urls;
|
||||
struct IGDdatas data;
|
||||
char lanaddr[N2N_NETMASK_STR_SIZE] = {'\0'};
|
||||
char lanport[6] = {'\0'};
|
||||
char externaladdr[N2N_NETMASK_STR_SIZE] = {'\0'};
|
||||
char externalport[6] = {'\0'};
|
||||
int ret = 0;
|
||||
|
||||
if(port == 0) {
|
||||
traceEvent(TRACE_ERROR, "invalid port");
|
||||
errorcode = -1;
|
||||
return errorcode;
|
||||
}
|
||||
snprintf(lanport, sizeof(lanport), "%d", port);
|
||||
memcpy(externalport, lanport, sizeof(externalport));
|
||||
|
||||
ret = n2n_UPNP_GetValidIGD(&urls, &data, lanaddr, externaladdr);
|
||||
if(ret != 0) {
|
||||
errorcode = -1;
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
// TCP port
|
||||
ret = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
|
||||
externalport, lanport, lanaddr, "n2n-vpn",
|
||||
"TCP", NULL, "0");
|
||||
if(ret != UPNPCOMMAND_SUCCESS) {
|
||||
traceEvent(TRACE_WARNING, "UPnP local TCP port %s mapping failed, code %d (%s)", lanport, ret, strupnperror(ret));
|
||||
errorcode = -1;
|
||||
} else
|
||||
traceEvent(TRACE_NORMAL, "UPnP added TCP port mapping: %s:%s -> %s:%s", externaladdr, externalport, lanaddr, lanport);
|
||||
|
||||
// UDP port
|
||||
ret = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
|
||||
externalport, lanport, lanaddr, "n2n-vpn",
|
||||
"UDP", NULL, "0");
|
||||
if(ret != UPNPCOMMAND_SUCCESS) {
|
||||
traceEvent(TRACE_WARNING, "UPnP local UDP port %s mapping failed, code %d (%s)", lanport, ret, strupnperror(ret));
|
||||
errorcode = -1;
|
||||
} else
|
||||
traceEvent(TRACE_NORMAL, "UPnP added UDP port mapping: %s:%s -> %s:%s", externaladdr, externalport, lanaddr, lanport);
|
||||
|
||||
FreeUPNPUrls(&urls);
|
||||
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
|
||||
static int n2n_upnp_del_port_mapping (const uint16_t port) {
|
||||
|
||||
int errorcode = 0;
|
||||
struct UPNPUrls urls;
|
||||
struct IGDdatas data;
|
||||
char lanaddr[N2N_NETMASK_STR_SIZE] = {'\0'};
|
||||
// char lanport[6] = {'\0'};
|
||||
char externaladdr[N2N_NETMASK_STR_SIZE] = {'\0'};
|
||||
char externalport[6] = {'\0'};
|
||||
int ret = 0;
|
||||
|
||||
if(port == 0) {
|
||||
traceEvent(TRACE_ERROR, "invalid port");
|
||||
errorcode = -1;
|
||||
return errorcode;
|
||||
}
|
||||
snprintf(externalport, sizeof(externalport), "%d", port);
|
||||
|
||||
ret = n2n_UPNP_GetValidIGD(&urls, &data, lanaddr, externaladdr);
|
||||
if(ret != 0) {
|
||||
errorcode = -1;
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
// TCP port
|
||||
ret = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, externalport, "TCP", NULL);
|
||||
if(ret != UPNPCOMMAND_SUCCESS) {
|
||||
traceEvent(TRACE_WARNING, "UPnP failed to delete TCP port mapping for %s:%s, code %d (%s)", externaladdr, externalport, ret, strupnperror(ret));
|
||||
errorcode = -1;
|
||||
} else
|
||||
traceEvent(TRACE_NORMAL, "UPnP deleted TCP port mapping for %s:%s", externaladdr, externalport);
|
||||
|
||||
// UDP port
|
||||
ret = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, externalport, "UDP", NULL);
|
||||
if(ret != UPNPCOMMAND_SUCCESS) {
|
||||
traceEvent(TRACE_WARNING, "UPnP failed to delete UDP port mapping for %s:%s, code %d (%s)", externaladdr, externalport, ret, strupnperror(ret));
|
||||
errorcode = -1;
|
||||
} else
|
||||
traceEvent(TRACE_NORMAL, "UPnP deleted UDP port mapping for %s:%s", externaladdr, externalport);
|
||||
|
||||
FreeUPNPUrls(&urls);
|
||||
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
#endif // HAVE_MINIUPNP
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifdef HAVE_NATPMP
|
||||
|
||||
static int n2n_natpmp_initialization (natpmp_t *natpmp, char *lanaddr, char *externaladdr) {
|
||||
|
||||
int errorcode = 0;
|
||||
natpmpresp_t response;
|
||||
int ret = 0;
|
||||
int forcegw = 0;
|
||||
in_addr_t gateway = 0;
|
||||
struct in_addr gateway_in_use;
|
||||
struct timeval timeout;
|
||||
fd_set fds;
|
||||
|
||||
ret = initnatpmp(natpmp, forcegw, gateway);
|
||||
if(ret != 0) {
|
||||
traceEvent(TRACE_WARNING, "NAT-PMP failed to initialize, code %d", ret);
|
||||
errorcode = -1;
|
||||
return errorcode;
|
||||
}
|
||||
gateway_in_use.s_addr = natpmp->gateway;
|
||||
traceEvent(TRACE_INFO, "NAT-PMP using gateway: %s", inet_ntoa(gateway_in_use));
|
||||
|
||||
ret = sendpublicaddressrequest(natpmp);
|
||||
if(ret != 2) {
|
||||
traceEvent(TRACE_WARNING, "NAT-PMP get external ip address failed, code %d", ret);
|
||||
closenatpmp(natpmp);
|
||||
errorcode = -1;
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(natpmp->s, &fds);
|
||||
getnatpmprequesttimeout(natpmp, &timeout);
|
||||
select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
|
||||
ret = readnatpmpresponseorretry(natpmp, &response);
|
||||
traceEvent(TRACE_INFO, "NAT-PMP read response returned %d (%s)", ret, ret == 0 ? "OK" : (ret == NATPMP_TRYAGAIN ? "TRY AGAIN" : "FAILED"));
|
||||
} while (ret == NATPMP_TRYAGAIN);
|
||||
|
||||
if(response.type != NATPMP_RESPTYPE_PUBLICADDRESS) {
|
||||
traceEvent(TRACE_WARNING, "NAT-PMP invalid response type %u", response.type);
|
||||
closenatpmp(natpmp);
|
||||
errorcode = -1;
|
||||
return errorcode;
|
||||
}
|
||||
snprintf(externaladdr, N2N_NETMASK_STR_SIZE, "%s", inet_ntoa(response.pnu.publicaddress.addr));
|
||||
snprintf(lanaddr, N2N_NETMASK_STR_SIZE, "localhost");
|
||||
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
|
||||
static int n2n_natpmp_port_mapping_request (natpmp_t *natpmp,
|
||||
const uint16_t port,
|
||||
const int protocol /* NATPMP_PROTOCOL_TCP or NATPMP_PROTOCOL_UDP */,
|
||||
const int method /* set:1 del:0 */) {
|
||||
|
||||
int errorcode = 0;
|
||||
natpmpresp_t response;
|
||||
int ret = 0;
|
||||
uint16_t lanport = 0;
|
||||
uint16_t externalport = 0;
|
||||
struct timeval timeout;
|
||||
fd_set fds;
|
||||
|
||||
if(port == 0) {
|
||||
traceEvent(TRACE_ERROR, "invalid port");
|
||||
errorcode = -1;
|
||||
return errorcode;
|
||||
}
|
||||
lanport = port;
|
||||
externalport = port;
|
||||
|
||||
ret = sendnewportmappingrequest(natpmp, protocol, lanport, externalport, (method ? 31104000 /* lifetime 360 days*/ : 0));
|
||||
if(ret != 12) {
|
||||
traceEvent(TRACE_WARNING, "NAT-PMP new port mapping request failed, code %d", ret);
|
||||
errorcode = -1;
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(natpmp->s, &fds);
|
||||
getnatpmprequesttimeout(natpmp, &timeout);
|
||||
select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
|
||||
ret = readnatpmpresponseorretry(natpmp, &response);
|
||||
traceEvent(TRACE_INFO, "NAT-PMP read response returned %d (%s)", ret, ret == 0 ? "OK" : (ret == NATPMP_TRYAGAIN ? "TRY AGAIN" : "FAILED"));
|
||||
} while (ret == NATPMP_TRYAGAIN);
|
||||
|
||||
if(!((response.type == NATPMP_RESPTYPE_TCPPORTMAPPING) || (response.type == NATPMP_RESPTYPE_UDPPORTMAPPING))) {
|
||||
traceEvent(TRACE_WARNING, "NAT-PMP invalid response type %u", response.type);
|
||||
errorcode = -1;
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
|
||||
static int n2n_natpmp_set_port_mapping (const uint16_t port) {
|
||||
|
||||
int errorcode = 0;
|
||||
natpmp_t natpmp;
|
||||
int ret = 0;
|
||||
char lanaddr[N2N_NETMASK_STR_SIZE] = {'\0'};
|
||||
uint16_t lanport = 0;
|
||||
char externaladdr[N2N_NETMASK_STR_SIZE] = {'\0'};
|
||||
uint16_t externalport = 0;
|
||||
|
||||
lanport = port;
|
||||
externalport = port;
|
||||
|
||||
ret = n2n_natpmp_initialization(&natpmp, lanaddr, externaladdr);
|
||||
if(ret != 0) {
|
||||
errorcode = -1;
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
// TCP port
|
||||
ret = n2n_natpmp_port_mapping_request(&natpmp, port, NATPMP_PROTOCOL_TCP, 1);
|
||||
if(ret != 0) {
|
||||
traceEvent(TRACE_WARNING, "NAT-PMP local TCP port %hu mapping failed", lanport);
|
||||
errorcode = -1;
|
||||
} else
|
||||
traceEvent(TRACE_NORMAL, "NAT-PMP added TCP port mapping: %s:%hu -> %s:%hu", externaladdr, externalport, lanaddr, lanport);
|
||||
|
||||
// UDP port
|
||||
ret = n2n_natpmp_port_mapping_request(&natpmp, port, NATPMP_PROTOCOL_UDP, 1);
|
||||
if(ret != 0) {
|
||||
traceEvent(TRACE_WARNING, "NAT-PMP local UDP port %hu mapping failed", lanport);
|
||||
errorcode = -1;
|
||||
} else
|
||||
traceEvent(TRACE_NORMAL, "NAT-PMP added UDP port mapping: %s:%hu -> %s:%hu", externaladdr, externalport, lanaddr, lanport);
|
||||
|
||||
closenatpmp(&natpmp);
|
||||
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
|
||||
static int n2n_natpmp_del_port_mapping (const uint16_t port) {
|
||||
|
||||
int errorcode = 0;
|
||||
natpmp_t natpmp;
|
||||
int ret = 0;
|
||||
char lanaddr[N2N_NETMASK_STR_SIZE] = {'\0'};
|
||||
// uint16_t lanport = 0;
|
||||
char externaladdr[N2N_NETMASK_STR_SIZE] = {'\0'};
|
||||
uint16_t externalport = 0;
|
||||
|
||||
// lanport = port;
|
||||
externalport = port;
|
||||
|
||||
ret = n2n_natpmp_initialization(&natpmp, lanaddr, externaladdr);
|
||||
if(ret != 0) {
|
||||
errorcode = -1;
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
// TCP port
|
||||
ret = n2n_natpmp_port_mapping_request(&natpmp, port, NATPMP_PROTOCOL_TCP, 0);
|
||||
if(ret != 0) {
|
||||
traceEvent(TRACE_WARNING, "NAT-PMP failed to delete TCP port mapping for %s:%hu", externaladdr, externalport);
|
||||
errorcode = -1;
|
||||
} else
|
||||
traceEvent(TRACE_NORMAL, "NAT-PMP deleted TCP port mapping for %s:%hu", externaladdr, externalport);
|
||||
|
||||
// UDP port
|
||||
ret = n2n_natpmp_port_mapping_request(&natpmp, port, NATPMP_PROTOCOL_UDP, 0);
|
||||
if(ret != 0) {
|
||||
traceEvent(TRACE_WARNING, "NAT-PMP failed to delete UDP port mapping for %s:%hu", externaladdr, externalport);
|
||||
errorcode = -1;
|
||||
} else
|
||||
traceEvent(TRACE_NORMAL, "NAT-PMP deleted UDP port mapping for %s:%hu", externaladdr, externalport);
|
||||
|
||||
closenatpmp(&natpmp);
|
||||
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
#endif // HAVE_NATPMP
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
static void n2n_set_port_mapping (const uint16_t port) {
|
||||
|
||||
#ifdef HAVE_NATPMP
|
||||
// since the NAT-PMP protocol is more concise than UPnP, NAT-PMP is preferred.
|
||||
if(n2n_natpmp_set_port_mapping(port))
|
||||
#endif // HAVE_NATPMP
|
||||
{
|
||||
#ifdef HAVE_MINIUPNP
|
||||
n2n_upnp_set_port_mapping(port);
|
||||
#endif // HAVE_MINIUPNP
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void n2n_del_port_mapping (const uint16_t port) {
|
||||
|
||||
#ifdef HAVE_NATPMP
|
||||
if(n2n_natpmp_del_port_mapping(port))
|
||||
#endif // HAVE_NATPMP
|
||||
{
|
||||
#ifdef HAVE_MINIUPNP
|
||||
n2n_upnp_del_port_mapping(port);
|
||||
#endif // HAVE_MINIUPNP
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
// public
|
||||
|
||||
|
||||
#ifdef HAVE_PTHREAD /* future management port subscriptions will deprecate the following temporary code */
|
||||
void n2n_chg_port_mapping (struct n2n_edge *eee, uint16_t port) {
|
||||
// write a port change request to param struct, it will be handled in the thread
|
||||
pthread_mutex_lock(&eee->port_map_parameter->access);
|
||||
eee->port_map_parameter->new_port = port;
|
||||
pthread_mutex_unlock(&eee->port_map_parameter->access);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
N2N_THREAD_RETURN_DATATYPE port_map_thread(N2N_THREAD_PARAMETER_DATATYPE p) {
|
||||
|
||||
#ifdef HAVE_PTHREAD /* future management port subscriptions will deprecate the following temporary code */
|
||||
n2n_port_map_parameter_t *param = (n2n_port_map_parameter_t*)p;
|
||||
|
||||
while(1) {
|
||||
sleep(2);
|
||||
pthread_mutex_lock(¶m->access);
|
||||
if(param->mapped_port != param->new_port) {
|
||||
if(param->mapped_port)
|
||||
n2n_del_port_mapping(param->mapped_port);
|
||||
if(param->new_port)
|
||||
n2n_set_port_mapping(param->new_port);
|
||||
param->mapped_port = param->new_port;
|
||||
}
|
||||
pthread_mutex_unlock(¶m->access);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0 /* to be used with future management port subscriptions */
|
||||
n2n_port_map_parameter_t *param = (n2n_port_map_parameter_t*)p;
|
||||
SOCKET socket_fd;
|
||||
fd_set socket_mask;
|
||||
struct timeval wait_time;
|
||||
int ret = 0;
|
||||
char udp_buf[N2N_PKT_BUF_SIZE];
|
||||
ssize_t msg_len;
|
||||
uint32_t addr_tmp = htonl(INADDR_LOOPBACK);
|
||||
n2n_sock_t sock_tmp;
|
||||
struct sockaddr_in sock;
|
||||
socklen_t sock_len;
|
||||
|
||||
// open a new socket ...
|
||||
socket_fd = open_socket(0 /* no specific port */, INADDR_LOOPBACK, 0 /* UDP */);
|
||||
if(socket_fd < 0) {
|
||||
traceEvent(TRACE_ERROR, "port_map_thread failed to open a socket to management port");
|
||||
return 0;
|
||||
}
|
||||
// ... and connect to local mgmt port
|
||||
sock_tmp.family = AF_INET;
|
||||
memcpy(&sock_tmp.addr.v4, &addr_tmp, IPV4_SIZE);
|
||||
sock_tmp.port = param->mgmt_port;
|
||||
sock_len = sizeof(sock);
|
||||
fill_sockaddr((struct sockaddr*)&sock, sock_len, &sock_tmp);
|
||||
connect(socket_fd, (struct sockaddr*)&sock, sock_len);
|
||||
|
||||
// prepare a subscription request in 'udp_buf' of length 'msg_len'
|
||||
// !!! dummy
|
||||
udp_buf[0] = '\n';
|
||||
msg_len = 1;
|
||||
send(socket_fd, udp_buf, msg_len, 0 /*flags*/);
|
||||
// note: 'msg_len' and 'sock' get re-used hereafter
|
||||
|
||||
while(1) {
|
||||
FD_ZERO(&socket_mask);
|
||||
FD_SET(socket_fd, &socket_mask);
|
||||
|
||||
wait_time.tv_sec = SOCKET_TIMEOUT_INTERVAL_SECS;
|
||||
wait_time.tv_usec = 0;
|
||||
|
||||
ret = select(socket_fd + 1, &socket_mask, NULL, NULL, &wait_time);
|
||||
|
||||
if(ret > 0) {
|
||||
if(FD_ISSET(socket_fd, &socket_mask)) {
|
||||
// get the data
|
||||
sock_len = sizeof(sock);
|
||||
msg_len = recv(socket_fd, udp_buf, N2N_PKT_BUF_SIZE, 0 /*flags*/);
|
||||
|
||||
// check message format, first message could be the still buffered answer to the subscription request
|
||||
// !!!
|
||||
if(1 /* !!! correct message format */) {
|
||||
// delete an eventually previous port mapping
|
||||
if(param->mapped_port)
|
||||
n2n_del_port_mapping(param->mapped_port);
|
||||
// extract port from message and set accordingly if valid
|
||||
param->mapped_port = 0; // !!!
|
||||
if(param->mapped_port)
|
||||
n2n_set_port_mapping(param->mapped_port);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0; /* should never happen */
|
||||
}
|
||||
|
||||
|
||||
int port_map_create_thread (n2n_port_map_parameter_t **param, uint16_t mgmt_port) {
|
||||
|
||||
#ifdef HAVE_PTHREAD
|
||||
int ret;
|
||||
|
||||
// create parameter structure
|
||||
*param = (n2n_port_map_parameter_t*)calloc(1, sizeof(n2n_port_map_parameter_t));
|
||||
if(*param) {
|
||||
// initialize
|
||||
(*param)->mgmt_port = mgmt_port;
|
||||
} else {
|
||||
traceEvent(TRACE_WARNING, "port_map_create_thread was unable to create parameter structure");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// create thread
|
||||
ret = pthread_create(&((*param)->id), NULL, port_map_thread, (void *)*param);
|
||||
if(ret) {
|
||||
traceEvent(TRACE_WARNING, "port_map_create_thread failed to create port mapping thread with error number %d", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void port_map_cancel_thread (n2n_port_map_parameter_t *param) {
|
||||
|
||||
#ifdef HAVE_PTHREAD
|
||||
pthread_cancel(param->id);
|
||||
if(param->mapped_port)
|
||||
n2n_del_port_mapping(param->mapped_port);
|
||||
free(param);
|
||||
#endif
|
||||
}
|
1
thirdparty/libnatpmp
vendored
Submodule
1
thirdparty/libnatpmp
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 4536032ae32268a45c073a4d5e91bbab4534773a
|
1
thirdparty/miniupnp
vendored
Submodule
1
thirdparty/miniupnp
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 77876aea5fd926ef25dce9af6b264c7b53d2b134
|
Loading…
Reference in New Issue
Block a user