diff --git a/include/n2n_typedefs.h b/include/n2n_typedefs.h index 4a796bd..f0c94e0 100644 --- a/include/n2n_typedefs.h +++ b/include/n2n_typedefs.h @@ -659,7 +659,7 @@ typedef struct n2n_edge_conf { char *encrypt_key; int register_interval; /**< Interval for supernode registration, also used for UDP NAT hole punching. */ int register_ttl; /**< TTL for registration packet when UDP NAT hole punching through supernode. */ - in_addr_t bind_address; /**< The address to bind to if provided (-b) */ + in_addr_t bind_address; /**< The address to bind to if provided */ n2n_sock_t preferred_sock; /**< propagated local sock for better p2p in LAN (-e) */ uint8_t preferred_sock_auto; /**< indicates desired auto detect for preferred sock */ int local_port; @@ -813,6 +813,7 @@ typedef struct n2n_sn { sn_stats_t stats; int daemon; /* If non-zero then daemonise. */ n2n_mac_t mac_addr; + in_addr_t bind_address; /* The address to bind to if provided */ uint16_t lport; /* Local UDP port to bind to. */ uint16_t mport; /* Management UDP port to bind to. */ int sock; /* Main socket for UDP traffic with edges. */ diff --git a/src/sn_utils.c b/src/sn_utils.c index 6d84176..cb1d6f5 100644 --- a/src/sn_utils.c +++ b/src/sn_utils.c @@ -745,6 +745,7 @@ int sn_init_defaults (n2n_sn_t *sss) { strncpy(sss->version, PACKAGE_VERSION, sizeof(n2n_version_t)); sss->version[sizeof(n2n_version_t) - 1] = '\0'; sss->daemon = 1; /* By defult run as a daemon. */ + sss->bind_address = INADDR_ANY; /* any address */ sss->lport = N2N_SN_LPORT_DEFAULT; sss->mport = N2N_SN_MGMT_PORT; sss->sock = -1; diff --git a/src/supernode.c b/src/supernode.c index 166ea07..93ce214 100644 --- a/src/supernode.c +++ b/src/supernode.c @@ -60,7 +60,7 @@ static void help (int level) { printf(" general usage: supernode (see supernode.conf)\n" "\n" " or supernode " - "[-p ] " + "[-p [:]] " "\n " "[-F ] " "\n options for under- " @@ -113,7 +113,8 @@ static void help (int level) { ); printf (" OPTIONS FOR THE UNDERLYING NETWORK CONNECTION\n"); printf (" ---------------------------------------------\n\n"); - printf(" -p | fixed local UDP port, defaults to %u\n", N2N_SN_LPORT_DEFAULT); + printf(" -p [:] | fixed local UDP port (defaults to %u) and optionally\n" + " | bind to sepcified local IP address only ('any' by default)\n", N2N_SN_LPORT_DEFAULT); printf(" -F | name of the supernode's federation, defaults to\n" " | '%s'\n", (char *)FEDERATION_NAME); printf(" -l | ip address or name, and port of known supernode\n"); @@ -167,14 +168,39 @@ static int setOption (int optkey, char *_optarg, n2n_sn_t *sss) { //traceEvent(TRACE_NORMAL, "Option %c = %s", optkey, _optarg ? _optarg : ""); switch(optkey) { - case 'p': /* local-port */ - sss->lport = atoi(_optarg); - - if(sss->lport == 0) - traceEvent(TRACE_WARNING, "bad local port format, defaulting to %u", N2N_SN_LPORT_DEFAULT); - // default is made sure in sn_init() + case 'p': { /* local-port */ + char* colon = strpbrk(_optarg, ":"); + if(colon) { /*ip address:port */ + *colon = 0; + sss->bind_address = ntohl(inet_addr(_optarg)); + sss->lport = atoi(++colon); + if(sss->bind_address == INADDR_NONE) { + traceEvent(TRACE_WARNING, "bad address to bind to, binding to any IP address"); + sss->bind_address = INADDR_ANY; + } + if(sss->lport == 0) { + traceEvent(TRACE_WARNING, "bad local port format, defaulting to %u", N2N_SN_LPORT_DEFAULT); + sss->lport = N2N_SN_LPORT_DEFAULT; + } + } else { /* ip address or port only */ + char* dot = strpbrk(_optarg, "."); + if(dot) { /* ip address only */ + sss->bind_address = ntohl(inet_addr(_optarg)); + if(sss->bind_address == INADDR_NONE) { + traceEvent(TRACE_WARNING, "bad address to bind to, binding to any IP address"); + sss->bind_address = INADDR_ANY; + } + } else { /* port only */ + sss->lport = atoi(_optarg); + if(sss->lport == 0) { + traceEvent(TRACE_WARNING, "bad local port format, defaulting to %u", N2N_SN_LPORT_DEFAULT); + sss->lport = N2N_SN_LPORT_DEFAULT; + } + } + } break; + } case 't': /* mgmt-port */ sss->mport = atoi(_optarg); @@ -603,7 +629,7 @@ int main (int argc, char * const argv[]) { traceEvent(TRACE_DEBUG, "traceLevel is %d", getTraceLevel()); - sss_node.sock = open_socket(sss_node.lport, INADDR_ANY, 0 /* UDP */); + sss_node.sock = open_socket(sss_node.lport, sss_node.bind_address, 0 /* UDP */); if(-1 == sss_node.sock) { traceEvent(TRACE_ERROR, "failed to open main socket. %s", strerror(errno)); exit(-2); @@ -612,7 +638,7 @@ int main (int argc, char * const argv[]) { } #ifdef N2N_HAVE_TCP - sss_node.tcp_sock = open_socket(sss_node.lport, INADDR_ANY, 1 /* TCP */); + sss_node.tcp_sock = open_socket(sss_node.lport, sss_node.bind_address, 1 /* TCP */); if(-1 == sss_node.tcp_sock) { traceEvent(TRACE_ERROR, "failed to open auxiliary TCP socket, %s", strerror(errno)); exit(-2); diff --git a/supernode.1 b/supernode.1 index 742b826..5e9be22 100644 --- a/supernode.1 +++ b/supernode.1 @@ -26,8 +26,9 @@ Lines starting with a "#" are ignored. An equal sign ('=') should be used between key and value. Example: -p=7777 .SH OPTIONS FOR THE UNDERLYING NETWORK CONNECTION .TP -\fB\-p \fR<\fIlocal_port\fR>, \fB\-\-local-port\fR=<\fIlocal_port\fR> -listen on this fixed local UDP port, defaults to 7654 +\fB\-p \fR[<\fIlocal_ip_address\fR>:]<\fIlocal_port\fR>, \fB\-\-local-port\fR=... +binds supernode to this fixed UDP port on 'any' local IP address, defaults to 7654. +Optionally, the edge can bind to the provided local ip address only. .TP \fB\-F \fR<\fIfed_name\fR> name of the supernode's federation, defaults to '*Federation' (see also N2N_FEDERATION in ENVIRONMENT)