From 43cfc4fe70bc6a16fb562b8d8bb00e0d6faf5c1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9sz=C3=A1ros=20Mih=C3=A1ly?= Date: Fri, 22 Sep 2017 14:56:56 +0200 Subject: [PATCH 01/17] Add collision test --- src/apps/natdiscovery/natdiscovery.c | 114 ++++++++++++++++++--------- 1 file changed, 75 insertions(+), 39 deletions(-) diff --git a/src/apps/natdiscovery/natdiscovery.c b/src/apps/natdiscovery/natdiscovery.c index 8c8ae67..cc09037 100644 --- a/src/apps/natdiscovery/natdiscovery.c +++ b/src/apps/natdiscovery/natdiscovery.c @@ -46,24 +46,23 @@ //////////////////////////////////////////////////// static int udp_fd = -1; -static ioa_addr real_local_addr; static int counter = 0; #ifdef __cplusplus -static int run_stunclient(ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780, int response_port, int change_ip, int change_port, int padding) +static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780, int response_port, int change_ip, int change_port, int padding) { int ret=0; if (response_port >= 0) { - addr_set_port(&real_local_addr, response_port); + addr_set_port(local_addr, response_port); } udp_fd = socket(remote_addr->ss.sa_family, SOCK_DGRAM, 0); if (udp_fd < 0) err(-1, NULL); - if (!addr_any(&real_local_addr)) { - if (addr_bind(udp_fd, &real_local_addr,0,1,UDP_SOCKET) < 0) + if (!addr_any(local_addr)) { + if (addr_bind(udp_fd, local_addr,0,1,UDP_SOCKET) < 0) err(-1, NULL); } @@ -137,10 +136,10 @@ static int run_stunclient(ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_a } - if (addr_get_from_sock(udp_fd, &real_local_addr) < 0) { + if (addr_get_from_sock(udp_fd, local_addr) < 0) { printf("%s: Cannot get address from local socket\n", __FUNCTION__); } else { - *port = addr_get_port(&real_local_addr); + *port = addr_get_port(local_addr); } { @@ -201,7 +200,7 @@ static int run_stunclient(ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_a addr_debug_print(1, other_addr, "Other addr: "); } addr_debug_print(1, reflexive_addr, "UDP reflexive addr"); - + addr_debug_print(1, local_addr, "Local addr: "); } else { printf("Cannot read the response\n"); } @@ -233,7 +232,7 @@ static int run_stunclient(ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_a #else -static int run_stunclient(ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780, int response_port, int change_ip, int change_port, int padding) +static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780, int response_port, int change_ip, int change_port, int padding) { int ret=0; stun_buffer buf; @@ -242,11 +241,11 @@ static int run_stunclient(ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_a if (udp_fd < 0) err(-1, NULL); - if (!addr_any(&real_local_addr)) { + if (!addr_any(local_addr)) { if (response_port >= 0) { - addr_set_port(&real_local_addr, response_port); + addr_set_port(local_addr, response_port); } - if (addr_bind(udp_fd, &real_local_addr,0,1,UDP_SOCKET) < 0) { + if (addr_bind(udp_fd, local_addr,0,1,UDP_SOCKET) < 0) { err(-1, NULL); } } @@ -279,10 +278,10 @@ static int run_stunclient(ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_a } - if (addr_get_from_sock(udp_fd, &real_local_addr) < 0) { + if (addr_get_from_sock(udp_fd, local_addr) < 0) { printf("%s: Cannot get address from local socket\n", __FUNCTION__); } else { - *port = addr_get_port(&real_local_addr); + *port = addr_get_port(local_addr); } @@ -337,7 +336,7 @@ static int run_stunclient(ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_a addr_debug_print(1, other_addr, "Other addr: "); } addr_debug_print(1, reflexive_addr, "UDP reflexive addr"); - + addr_debug_print(1, local_addr, "Local addr: "); } else { printf("Cannot read the response\n"); } @@ -380,17 +379,21 @@ static char Usage[] = "Options:\n" " -m NAT mapping behavior discovery\n" " -f NAT filtering behavior discovery\n" + " -c NAT collision behavior discovery\n" + " Requires an alternative IP address (-A)\n" " -p STUN server port (Default: 3478)\n" - " -L Local address to use (optional)\n"; + " -L Local address to use (optional)\n" + " -A Local alrernative address to use\n" + " Used by collision behavior Discovery\n"; ////////////////////////////////////////////////// -static void init(ioa_addr *real_local_addr,ioa_addr *remote_addr,int *local_port,int port, int *rfc5780, char* local_addr, char* remote_param) +static void init(ioa_addr *local_addr,ioa_addr *remote_addr,int *local_port,int port, int *rfc5780, char* local_addr_string, char* remote_param) { - addr_set_any(real_local_addr); + addr_set_any(local_addr); - if(local_addr[0]) { - if(make_ioa_addr((const u08bits*)local_addr, 0, real_local_addr)<0) { + if(local_addr_string[0]) { + if(make_ioa_addr((const u08bits*)local_addr_string, 0, local_addr)<0) { err(-1,NULL); } } @@ -411,24 +414,27 @@ static void discoveryresult(const char *decision){ int main(int argc, char **argv) { int port = DEFAULT_STUN_PORT; - char local_addr[256]="\0"; + char local_addr_string[256]="\0"; + char local2_addr_string[256]="\0"; int c=0; int mapping = 0; int filtering = 0; + int collision = 0; int local_port, rfc5780; - ioa_addr other_addr, reflexive_addr, tmp_addr, remote_addr; + ioa_addr other_addr, reflexive_addr, tmp_addr, remote_addr, local_addr, local2_addr; set_logfile("stdout"); set_system_parameters(0); - ns_bzero(local_addr, sizeof(local_addr)); + ns_bzero(local_addr_string, sizeof(local_addr_string)); + ns_bzero(local2_addr_string, sizeof(local2_addr_string)); addr_set_any(&remote_addr); addr_set_any(&other_addr); addr_set_any(&reflexive_addr); addr_set_any(&tmp_addr); - while ((c = getopt(argc, argv, "mfp:L:")) != -1) { + while ((c = getopt(argc, argv, "mfcp:L:A:")) != -1) { switch(c) { case 'm': mapping=1; @@ -436,11 +442,17 @@ int main(int argc, char **argv) case 'f': filtering=1; break; + case 'c': + collision=1; + break; case 'p': port = atoi(optarg); break; case 'L': - STRCPY(local_addr, optarg); + STRCPY(local_addr_string, optarg); + break; + case 'A': + STRCPY(local2_addr_string, optarg); break; default: fprintf(stderr,"%s\n", Usage); @@ -452,12 +464,18 @@ int main(int argc, char **argv) fprintf(stderr, "%s\n", Usage); exit(-1); } + + if(collision && local2_addr_string == '\0'){ + fprintf(stderr, "Use \"-A\" to add an Alternative local IP address.\n"); + fprintf(stderr, "It is mandatory with \"-c\" collision behavior detection..\n"); + exit(-1); + } - init(&real_local_addr, &remote_addr, &local_port, port, &rfc5780, local_addr, argv[optind]); + init(&local_addr, &remote_addr, &local_port, port, &rfc5780, local_addr_string, argv[optind]); - if (mapping) { - run_stunclient(&remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,0); - if (addr_eq(&real_local_addr,&reflexive_addr)){ + if(mapping) { + run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,0); + if (addr_eq(&local_addr,&reflexive_addr)){ discoveryresult("No NAT! (Endpoint Independent Mapping)"); } if(rfc5780) { @@ -467,14 +485,14 @@ int main(int argc, char **argv) addr_cpy(&remote_addr, &other_addr); addr_set_port(&remote_addr, port); - run_stunclient(&remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,0); + run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,0); if(addr_eq(&tmp_addr,&reflexive_addr)){ discoveryresult("NAT with Enpoint Independent Mapping!"); } else { addr_cpy(&tmp_addr, &reflexive_addr); addr_cpy(&remote_addr, &other_addr); - run_stunclient(&remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,0); + run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,0); if(addr_eq(&tmp_addr,&reflexive_addr)){ discoveryresult("NAT with Address Dependent Mapping!"); } else { @@ -486,22 +504,22 @@ int main(int argc, char **argv) } } - init(&real_local_addr, &remote_addr, &local_port, port, &rfc5780, local_addr, argv[optind]); + init(&local_addr, &remote_addr, &local_port, port, &rfc5780, local_addr_string, argv[optind]); - if (filtering) { - run_stunclient(&remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,0); - if (addr_eq(&real_local_addr,&reflexive_addr)){ + if(filtering) { + run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,0); + if(addr_eq(&local_addr, &reflexive_addr)){ discoveryresult("No NAT! (Endpoint Independent Mapping)"); } if(rfc5780) { if(!addr_any(&other_addr)){ int res=0; - res=run_stunclient(&remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,1,1,0); + res=run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,1,1,0); if (!res) { discoveryresult("NAT with Enpoint Independent Filtering!"); } else { res=0; - res=run_stunclient(&remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,1,0); + res=run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,1,0); if(!res){ discoveryresult("NAT with Address Dependent Filtering!"); } else { @@ -512,8 +530,26 @@ int main(int argc, char **argv) } } } - if (!filtering && !mapping) { - printf("Please use either -f or -m parameter for Filtering or Mapping behavior discovery.\n"); + + init(&local_addr, &remote_addr, &local_port, port, &rfc5780, local_addr_string, argv[optind]); + + if(collision) { + addr_set_any(&local2_addr); + + if(local2_addr_string[0]) { + if(make_ioa_addr((const u08bits*)local2_addr_string, 0, &local2_addr)<0) { + err(-1,NULL); + } + } + + run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,0); + addr_set_port(&local2_addr,addr_get_port(&local_addr)); + run_stunclient(&local2_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,0); + } + + if (!filtering && !mapping && !collision) { + printf("Please use either -f or -c or -m parameter for Filtering or Mapping behavior discovery.\n"); + } socket_closesocket(udp_fd); From 2848bbdda4b7bb68c648e4e85ecaf5f237db67f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9sz=C3=A1ros=20Mih=C3=A1ly?= Date: Tue, 26 Sep 2017 09:34:31 +0200 Subject: [PATCH 02/17] Add man collision --- README.turnutils | 7 ++++++- man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 2 +- man/man1/turnutils.1 | 13 +++++++++++-- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/README.turnutils b/README.turnutils index 91c09b4..ae9bda4 100644 --- a/README.turnutils +++ b/README.turnutils @@ -264,7 +264,7 @@ Address-Dependent, or Address and Port-Dependent Mapping and/or to determine if that NAT is currently using Endpoint-Independent, Address-Dependent, or Address and Port-Dependent Filtering. -Use either -m and/or -f flag to discover NAT Mapping and/or Filtering. +Use either -m, -f, -c flag to discover NAT behavior. Flags: @@ -272,12 +272,17 @@ Flags: -f NAT filtering behavior discovery +-c NAT collision behavior discovery + Options with required values: -p STUN server port (Default: 3478) -L Local address to use (optional) +-A Secondary Local address (optional) + Required for collision discovery + Usage: $ turnutils_natdiscovery -m -f stun.example.com diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index cd2c585..9ffb8a0 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "13 November 2016" "" "" +.TH TURN 1 "29 September 2017" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index 8852fb5..70258b1 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "13 November 2016" "" "" +.TH TURN 1 "29 September 2017" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 8182b99..af25b7d 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "13 November 2016" "" "" +.TH TURN 1 "29 September 2017" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used @@ -403,7 +403,7 @@ Address\-Dependent, or Address and Port\-Dependent Mapping and/or to determine i that NAT is currently using Endpoint\-Independent, Address\-Dependent, or Address and Port\-Dependent Filtering. .PP -Use either \fB\-m\fP and/or \fB\-f\fP flag to discover NAT Mapping and/or Filtering. +Use either \fB\-m\fP, \fB\-f\fP, \fB\-c\fP flag to discover NAT behavior. .PP Flags: .TP @@ -414,6 +414,10 @@ NAT mapping behavior discovery .B \fB\-f\fP NAT filtering behavior discovery +.TP +.B +\fB\-c\fP +NAT collision behavior discovery .PP Options with required values: .TP @@ -424,6 +428,11 @@ STUN server port (Default: 3478) .B \fB\-L\fP Local address to use (optional) +.TP +.B +\fB\-A\fP +Secondary Local address (optional) +Required for collision discovery .PP Usage: .PP From e93bbd213727714421a013008477e2f20e1c805c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9sz=C3=A1ros=20Mih=C3=A1ly?= Date: Tue, 26 Sep 2017 13:31:40 +0200 Subject: [PATCH 03/17] Add padding and tidy --- src/apps/natdiscovery/natdiscovery.c | 111 ++++++++++++++------------- 1 file changed, 57 insertions(+), 54 deletions(-) diff --git a/src/apps/natdiscovery/natdiscovery.c b/src/apps/natdiscovery/natdiscovery.c index cc09037..5cb6e8c 100644 --- a/src/apps/natdiscovery/natdiscovery.c +++ b/src/apps/natdiscovery/natdiscovery.c @@ -381,7 +381,9 @@ static char Usage[] = " -f NAT filtering behavior discovery\n" " -c NAT collision behavior discovery\n" " Requires an alternative IP address (-A)\n" - " -p STUN server port (Default: 3478)\n" + " -P Add 1500 byte Padding to the behavior discovery\n" + " Applicable with all except NAT Binding Lifetime discovery\n" + " -p STUN server port (Default: 3478)\n" " -L Local address to use (optional)\n" " -A Local alrernative address to use\n" " Used by collision behavior Discovery\n"; @@ -420,6 +422,7 @@ int main(int argc, char **argv) int mapping = 0; int filtering = 0; int collision = 0; + int padding = 0; int local_port, rfc5780; ioa_addr other_addr, reflexive_addr, tmp_addr, remote_addr, local_addr, local2_addr; @@ -434,7 +437,7 @@ int main(int argc, char **argv) addr_set_any(&reflexive_addr); addr_set_any(&tmp_addr); - while ((c = getopt(argc, argv, "mfcp:L:A:")) != -1) { + while ((c = getopt(argc, argv, "mfcPp:L:A:")) != -1) { switch(c) { case 'm': mapping=1; @@ -444,6 +447,9 @@ int main(int argc, char **argv) break; case 'c': collision=1; + break; + case 'P': + padding=1; break; case 'p': port = atoi(optarg); @@ -474,59 +480,57 @@ int main(int argc, char **argv) init(&local_addr, &remote_addr, &local_port, port, &rfc5780, local_addr_string, argv[optind]); if(mapping) { - run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,0); - if (addr_eq(&local_addr,&reflexive_addr)){ - discoveryresult("No NAT! (Endpoint Independent Mapping)"); - } - if(rfc5780) { - if(!addr_any(&other_addr)){ - addr_cpy(&tmp_addr, &reflexive_addr); - - addr_cpy(&remote_addr, &other_addr); - addr_set_port(&remote_addr, port); - - run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,0); - - if(addr_eq(&tmp_addr,&reflexive_addr)){ - discoveryresult("NAT with Enpoint Independent Mapping!"); - } else { + run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,padding); + if (addr_eq(&local_addr,&reflexive_addr)){ + discoveryresult("No NAT! (Endpoint Independent Mapping)"); + } + if(rfc5780) { + if(!addr_any(&other_addr)){ addr_cpy(&tmp_addr, &reflexive_addr); - addr_cpy(&remote_addr, &other_addr); - run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,0); - if(addr_eq(&tmp_addr,&reflexive_addr)){ - discoveryresult("NAT with Address Dependent Mapping!"); - } else { - discoveryresult("NAT with Address and Port Dependent Mapping!"); - } - }; + addr_cpy(&remote_addr, &other_addr); + addr_set_port(&remote_addr, port); + + run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,padding); + + if(addr_eq(&tmp_addr,&reflexive_addr)){ + discoveryresult("NAT with Enpoint Independent Mapping!"); + } else { + addr_cpy(&tmp_addr, &reflexive_addr); + addr_cpy(&remote_addr, &other_addr); + run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,padding); + if(addr_eq(&tmp_addr,&reflexive_addr)){ + discoveryresult("NAT with Address Dependent Mapping!"); + } else { + discoveryresult("NAT with Address and Port Dependent Mapping!"); + } + } } } } - init(&local_addr, &remote_addr, &local_port, port, &rfc5780, local_addr_string, argv[optind]); + init(&local_addr, &remote_addr, &local_port, port, &rfc5780, local_addr_string, argv[optind]); if(filtering) { - run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,0); - if(addr_eq(&local_addr, &reflexive_addr)){ - discoveryresult("No NAT! (Endpoint Independent Mapping)"); - } - if(rfc5780) { - if(!addr_any(&other_addr)){ - int res=0; - res=run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,1,1,0); - if (!res) { - discoveryresult("NAT with Enpoint Independent Filtering!"); - } else { - res=0; - res=run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,1,0); - if(!res){ - discoveryresult("NAT with Address Dependent Filtering!"); + run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,padding); + if(addr_eq(&local_addr, &reflexive_addr)){ + discoveryresult("No NAT! (Endpoint Independent Mapping)"); + } + if(rfc5780) { + if(!addr_any(&other_addr)){ + int res=0; + res=run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,1,1,padding); + if (!res) { + discoveryresult("NAT with Enpoint Independent Filtering!"); } else { - discoveryresult("NAT with Address and Port Dependent Filtering!"); + res=0; + res=run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,1,padding); + if(!res){ + discoveryresult("NAT with Address Dependent Filtering!"); + } else { + discoveryresult("NAT with Address and Port Dependent Filtering!"); + } } - }; - } } } @@ -534,22 +538,21 @@ int main(int argc, char **argv) init(&local_addr, &remote_addr, &local_port, port, &rfc5780, local_addr_string, argv[optind]); if(collision) { - addr_set_any(&local2_addr); + addr_set_any(&local2_addr); - if(local2_addr_string[0]) { - if(make_ioa_addr((const u08bits*)local2_addr_string, 0, &local2_addr)<0) { - err(-1,NULL); - } + if(local2_addr_string[0]) { + if(make_ioa_addr((const u08bits*)local2_addr_string, 0, &local2_addr)<0) { + err(-1,NULL); } + } - run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,0); - addr_set_port(&local2_addr,addr_get_port(&local_addr)); - run_stunclient(&local2_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,0); + run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,padding); + addr_set_port(&local2_addr,addr_get_port(&local_addr)); + run_stunclient(&local2_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,padding); } if (!filtering && !mapping && !collision) { printf("Please use either -f or -c or -m parameter for Filtering or Mapping behavior discovery.\n"); - } socket_closesocket(udp_fd); From 22cc19e53ce1b7aef5e6ddb13a8908cc2e8f168b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9sz=C3=A1ros=20Mih=C3=A1ly?= Date: Wed, 27 Sep 2017 08:32:39 +0200 Subject: [PATCH 04/17] Add ALG detection discovery --- src/apps/natdiscovery/natdiscovery.c | 34 ++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/apps/natdiscovery/natdiscovery.c b/src/apps/natdiscovery/natdiscovery.c index 5cb6e8c..ceb1d05 100644 --- a/src/apps/natdiscovery/natdiscovery.c +++ b/src/apps/natdiscovery/natdiscovery.c @@ -196,11 +196,24 @@ static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr turn::StunAttrAddr addr2(iter2); addr2.getAddr(response_origin); addr_debug_print(1, &response_origin, "Response origin: "); - } + + turn::StunAttrIterator iter3(res,STUN_ATTRIBUTE_MAPPED_ADDRESS); + if (!iter3.eof()) { + ioa_addr mapped_addr; + addr_set_any(mapped_addr); + turn::StunAttrAddr addr3(iter3); + addr3.getAddr(mapped_addr); + if (!addr_eq(mapped_addr,reflexive_addr)){ + printf("\n -= ALG detected! Mapped and XOR-Mapped differ! =-\n"); + addr_debug_print(1, &response_origin, "Mapped Address: "); + } + } else { + printf("Not received mapped address attribute!\n"); + } addr_debug_print(1, other_addr, "Other addr: "); } addr_debug_print(1, reflexive_addr, "UDP reflexive addr"); - addr_debug_print(1, local_addr, "Local addr: "); + addr_debug_print(1, local_addr, "Local addr: "); } else { printf("Cannot read the response\n"); } @@ -222,7 +235,7 @@ static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr }else{ printf("The response is not a well formed STUN message\n"); } - ret=1; + ret=1; } } close(udp_fd); @@ -331,12 +344,23 @@ static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr if (sar) { ioa_addr response_origin; stun_attr_get_addr_str((u08bits *) buf.buf, (size_t) buf.len, sar, &response_origin, NULL); - addr_debug_print(1, &response_origin, "Response origin: "); + addr_debug_print(1, &response_origin, "Response origin: "); + ioa_addr mapped_addr; + addr_set_any(&mapped_addr); + if (stun_attr_get_first_addr(&buf, STUN_ATTRIBUTE_MAPPED_ADDRESS, &mapped_addr, NULL) >= 0) { + if (!addr_eq(&mapped_addr,reflexive_addr)){ + printf("\n -= ALG detected! Mapped and XOR-Mapped differ! =-\n"); + addr_debug_print(1, &response_origin, "Mapped Address: "); + } + } else { + printf("Not received mapped address attribute!\n"); + } + } addr_debug_print(1, other_addr, "Other addr: "); } addr_debug_print(1, reflexive_addr, "UDP reflexive addr"); - addr_debug_print(1, local_addr, "Local addr: "); + addr_debug_print(1, local_addr, "Local addr: "); } else { printf("Cannot read the response\n"); } From 87866887d38bea99371915216a488f5e3c4c0dfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9sz=C3=A1ros=20Mih=C3=A1ly?= Date: Thu, 28 Sep 2017 00:55:11 +0200 Subject: [PATCH 05/17] ALG fix --- src/apps/natdiscovery/natdiscovery.c | 53 +++++++++++++++------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/src/apps/natdiscovery/natdiscovery.c b/src/apps/natdiscovery/natdiscovery.c index ceb1d05..49050d3 100644 --- a/src/apps/natdiscovery/natdiscovery.c +++ b/src/apps/natdiscovery/natdiscovery.c @@ -188,7 +188,21 @@ static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *rfc5780 = 1; printf("\n========================================\n"); printf("RFC 5780 response %d\n",++counter); - turn::StunAttrAddr addr1(iter1); + turn::StunAttrIterator iter0(res,STUN_ATTRIBUTE_MAPPED_ADDRESS); + if (!iter0.eof()) { + ioa_addr mapped_addr; + addr_set_any(mapped_addr); + turn::StunAttrAddr addr0(iter0); + addr0.getAddr(mapped_addr); + if (!addr_eq(mapped_addr,reflexive_addr)){ + printf("-= ALG detected! Mapped and XOR-Mapped differ! =-\n"); + addr_debug_print(1, &mapped_addr, "Mapped Address: "); + } else { + printf("No ALG: Mapped and XOR-Mapped is equal.\n"); + } + } else { + printf("Not received mapped address attribute!\n"); + } turn::StunAttrAddr addr1(iter1); addr1.getAddr(*other_addr); turn::StunAttrIterator iter2(res,STUN_ATTRIBUTE_RESPONSE_ORIGIN); if (!iter2.eof()) { @@ -197,19 +211,7 @@ static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr addr2.getAddr(response_origin); addr_debug_print(1, &response_origin, "Response origin: "); - turn::StunAttrIterator iter3(res,STUN_ATTRIBUTE_MAPPED_ADDRESS); - if (!iter3.eof()) { - ioa_addr mapped_addr; - addr_set_any(mapped_addr); - turn::StunAttrAddr addr3(iter3); - addr3.getAddr(mapped_addr); - if (!addr_eq(mapped_addr,reflexive_addr)){ - printf("\n -= ALG detected! Mapped and XOR-Mapped differ! =-\n"); - addr_debug_print(1, &response_origin, "Mapped Address: "); - } - } else { - printf("Not received mapped address attribute!\n"); - } + addr_debug_print(1, other_addr, "Other addr: "); } addr_debug_print(1, reflexive_addr, "UDP reflexive addr"); @@ -339,23 +341,24 @@ static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *rfc5780 = 1; printf("\n========================================\n"); printf("RFC 5780 response %d\n",++counter); + ioa_addr mapped_addr; + addr_set_any(&mapped_addr); + if (stun_attr_get_first_addr(&buf, STUN_ATTRIBUTE_MAPPED_ADDRESS, &mapped_addr, NULL) >= 0) { + if (!addr_eq(&mapped_addr,reflexive_addr)){ + printf("-= ALG detected! Mapped and XOR-Mapped differ! =-\n"); + addr_debug_print(1, &mapped_addr, "Mapped Address: "); + }else { + printf("No ALG: Mapped and XOR-Mapped is equal.\n"); + } + } else { + printf("Not received mapped address attribute.\n"); + } stun_attr_get_addr_str((u08bits *) buf.buf, (size_t) buf.len, sar, other_addr, NULL); sar = stun_attr_get_first_by_type_str(buf.buf, buf.len, STUN_ATTRIBUTE_RESPONSE_ORIGIN); if (sar) { ioa_addr response_origin; stun_attr_get_addr_str((u08bits *) buf.buf, (size_t) buf.len, sar, &response_origin, NULL); addr_debug_print(1, &response_origin, "Response origin: "); - ioa_addr mapped_addr; - addr_set_any(&mapped_addr); - if (stun_attr_get_first_addr(&buf, STUN_ATTRIBUTE_MAPPED_ADDRESS, &mapped_addr, NULL) >= 0) { - if (!addr_eq(&mapped_addr,reflexive_addr)){ - printf("\n -= ALG detected! Mapped and XOR-Mapped differ! =-\n"); - addr_debug_print(1, &response_origin, "Mapped Address: "); - } - } else { - printf("Not received mapped address attribute!\n"); - } - } addr_debug_print(1, other_addr, "Other addr: "); } From 24919cb8f418bcd6b911e5feda4d142368650de6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9sz=C3=A1ros=20Mih=C3=A1ly?= Date: Wed, 27 Sep 2017 21:50:34 +0200 Subject: [PATCH 06/17] refactor stun client (send/receive) --- src/apps/natdiscovery/natdiscovery.c | 696 ++++++++++++++------------- 1 file changed, 355 insertions(+), 341 deletions(-) diff --git a/src/apps/natdiscovery/natdiscovery.c b/src/apps/natdiscovery/natdiscovery.c index 49050d3..a33f5f6 100644 --- a/src/apps/natdiscovery/natdiscovery.c +++ b/src/apps/natdiscovery/natdiscovery.c @@ -1,32 +1,32 @@ /* - * Copyright (C) 2011, 2012, 2013 Citrix Systems - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of the project nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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. - */ +* Copyright (C) 2011, 2012, 2013 Citrix Systems +* +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. 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. +* 3. Neither the name of the project nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 @@ -44,37 +44,23 @@ #endif //////////////////////////////////////////////////// - static int udp_fd = -1; +static int udp_fd2 = -1; + static int counter = 0; #ifdef __cplusplus -static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780, int response_port, int change_ip, int change_port, int padding) -{ + +static int stunclient_send(int sockfd, ioa_addr *remote_addr, int change_ip, int change_port, int padding, int response_port){ int ret=0; - if (response_port >= 0) { - addr_set_port(local_addr, response_port); - } - udp_fd = socket(remote_addr->ss.sa_family, SOCK_DGRAM, 0); - if (udp_fd < 0) - err(-1, NULL); - - if (!addr_any(local_addr)) { - if (addr_bind(udp_fd, local_addr,0,1,UDP_SOCKET) < 0) - err(-1, NULL); - } - - - - turn::StunMsgRequest req(STUN_METHOD_BINDING); req.constructBindingRequest(); if (response_port >= 0) { - turn::StunAttrResponsePort rpa; + turn::StunAttrResponsePort rpa; rpa.setResponsePort((u16bits)response_port); try { req.addAttr(rpa); @@ -128,15 +114,21 @@ static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr int slen = get_ioa_addr_len(remote_addr); do { - len = sendto(udp_fd, req.getRawBuffer(), req.getSize(), 0, (struct sockaddr*) remote_addr, (socklen_t) slen); + len = sendto(sockfd, req.getRawBuffer(), req.getSize(), 0, (struct sockaddr*) remote_addr, (socklen_t) slen); } while (len < 0 && ((errno == EINTR) || (errno == ENOBUFS) || (errno == EAGAIN))); if (len < 0) - err(-1, NULL); + err(-1, NULL); } - if (addr_get_from_sock(udp_fd, local_addr) < 0) { +} + + +static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780){ + int ret=0; + + if (addr_get_from_sock(sockfd, local_addr) < 0) { printf("%s: Cannot get address from local socket\n", __FUNCTION__); } else { *port = addr_get_port(local_addr); @@ -153,10 +145,10 @@ static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr tv.tv_sec = 3; /* 3 Secs Timeout */ tv.tv_usec = 0; // Not init'ing this can cause strange errors - setsockopt(udp_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval)); + setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval)); do { - len = recv(udp_fd, ptr, to_recv - recvd, 0); + len = recv(sockfd, ptr, to_recv - recvd, 0); if (len > 0) { recvd += len; ptr += len; @@ -165,7 +157,7 @@ static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr } while (len < 0 && (errno == EINTR)); if (recvd > 0) - len = recvd; + len = recvd; buf.len = len; try { @@ -196,7 +188,7 @@ static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr addr0.getAddr(mapped_addr); if (!addr_eq(mapped_addr,reflexive_addr)){ printf("-= ALG detected! Mapped and XOR-Mapped differ! =-\n"); - addr_debug_print(1, &mapped_addr, "Mapped Address: "); + addr_debug_print(1, &mapped_addr, "Mapped Address: "); } else { printf("No ALG: Mapped and XOR-Mapped is equal.\n"); } @@ -211,377 +203,399 @@ static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr addr2.getAddr(response_origin); addr_debug_print(1, &response_origin, "Response origin: "); - - addr_debug_print(1, other_addr, "Other addr: "); + + addr_debug_print(1, other_addr, "Other addr: "); + } + addr_debug_print(1, reflexive_addr, "UDP reflexive addr"); + addr_debug_print(1, local_addr, "Local addr: "); + } else { + printf("Cannot read the response\n"); } - addr_debug_print(1, reflexive_addr, "UDP reflexive addr"); - addr_debug_print(1, local_addr, "Local addr: "); } else { - printf("Cannot read the response\n"); + printf("Wrong type of response\n"); } } else { - printf("Wrong type of response\n"); + int err_code = res.getError(); + std::string reason = res.getReason(); + + printf("The response is an error %d (%s)\n", err_code, reason.c_str()); } } else { - int err_code = res.getError(); - std::string reason = res.getReason(); - - printf("The response is an error %d (%s)\n", err_code, reason.c_str()); + printf("The response is not a reponse message\n"); } - } else { - printf("The response is not a reponse message\n"); + } catch(...) { + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { + printf("STUN receive timeout..\n"); + }else{ + printf("The response is not a well formed STUN message\n"); + } + ret=1; } - } catch(...) { - if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { - printf("STUN receive timeout..\n"); - }else{ - printf("The response is not a well formed STUN message\n"); - } - ret=1; } } - close(udp_fd); - return ret; -} + static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780, int change_ip, int change_port, int padding){ + int ret=0; + + udp_fd = socket(remote_addr->ss.sa_family, SOCK_DGRAM, 0); + if (udp_fd < 0) + err(-1, NULL); + + if (!addr_any(local_addr)) { + if (addr_bind(udp_fd, local_addr,0,1,UDP_SOCKET) < 0) + err(-1, NULL); + } + + ret=stunclient_send(udp_fd, remote_addr, change_ip, change_port, padding, -1); + ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, port, rfc5780); + close(udp_fd); + + return ret; + } #else -static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780, int response_port, int change_ip, int change_port, int padding) -{ - int ret=0; - stun_buffer buf; + static int stunclient_send(int sockfd, ioa_addr *remote_addr, int change_ip, int change_port, int padding, int response_port){ + int ret=0; + stun_buffer buf; - udp_fd = socket(remote_addr->ss.sa_family, CLIENT_DGRAM_SOCKET_TYPE, CLIENT_DGRAM_SOCKET_PROTOCOL); - if (udp_fd < 0) - err(-1, NULL); + stun_prepare_binding_request(&buf); - if (!addr_any(local_addr)) { if (response_port >= 0) { - addr_set_port(local_addr, response_port); - } - if (addr_bind(udp_fd, local_addr,0,1,UDP_SOCKET) < 0) { + stun_attr_add_response_port_str((u08bits*) (buf.buf), (size_t*) &(buf.len), (u16bits) response_port); + } + if (change_ip || change_port) { + stun_attr_add_change_request_str((u08bits*) buf.buf, (size_t*) &(buf.len), change_ip, change_port); + } + if (padding) { + if(stun_attr_add_padding_str((u08bits*) buf.buf, (size_t*) &(buf.len), 1500)<0) { + printf("%s: ERROR: Cannot add padding\n",__FUNCTION__); + } + } + + { + int len = 0; + int slen = get_ioa_addr_len(remote_addr); + + do { + len = sendto(sockfd, buf.buf, buf.len, 0, (struct sockaddr*) remote_addr, (socklen_t) slen); + } while (len < 0 && ((errno == EINTR) || (errno == ENOBUFS) || (errno == EAGAIN))); + + if (len < 0) err(-1, NULL); - } - } - - stun_prepare_binding_request(&buf); - - if (response_port >= 0) { - stun_attr_add_response_port_str((u08bits*) (buf.buf), (size_t*) &(buf.len), (u16bits) response_port); - } - if (change_ip || change_port) { - stun_attr_add_change_request_str((u08bits*) buf.buf, (size_t*) &(buf.len), change_ip, change_port); - } - if (padding) { - if(stun_attr_add_padding_str((u08bits*) buf.buf, (size_t*) &(buf.len), 1500)<0) { - printf("%s: ERROR: Cannot add padding\n",__FUNCTION__); } } + static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780){ + int ret=0; - { - int len = 0; - int slen = get_ioa_addr_len(remote_addr); + if (addr_get_from_sock(sockfd, local_addr) < 0) { + printf("%s: Cannot get address from local socket\n", __FUNCTION__); + } else { + *port = addr_get_port(local_addr); + } - do { - len = sendto(udp_fd, buf.buf, buf.len, 0, (struct sockaddr*) remote_addr, (socklen_t) slen); - } while (len < 0 && ((errno == EINTR) || (errno == ENOBUFS) || (errno == EAGAIN))); - if (len < 0) - err(-1, NULL); + { + int len = 0; + u08bits *ptr = buf.buf; + int recvd = 0; + const int to_recv = sizeof(buf.buf); + struct timeval tv; - } + tv.tv_sec = 3; /* 3 Secs Timeout */ + tv.tv_usec = 0; // Not init'ing this can cause strange errors - if (addr_get_from_sock(udp_fd, local_addr) < 0) { - printf("%s: Cannot get address from local socket\n", __FUNCTION__); - } else { - *port = addr_get_port(local_addr); - } + setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval)); - - { - int len = 0; - u08bits *ptr = buf.buf; - int recvd = 0; - const int to_recv = sizeof(buf.buf); - struct timeval tv; + do { + len = recv(sockfd, ptr, to_recv - recvd, 0); + if (len > 0) { + recvd += len; + ptr += len; + break; + } + } while (len < 0 && (errno == EINTR)); - tv.tv_sec = 3; /* 3 Secs Timeout */ - tv.tv_usec = 0; // Not init'ing this can cause strange errors - - setsockopt(udp_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval)); - - do { - len = recv(udp_fd, ptr, to_recv - recvd, 0); - if (len > 0) { - recvd += len; - ptr += len; - break; - } - } while (len < 0 && (errno == EINTR)); - - if (recvd > 0) + if (recvd > 0) len = recvd; - buf.len = len; + buf.len = len; - if (stun_is_command_message(&buf)) { + if (stun_is_command_message(&buf)) { - if (stun_is_response(&buf)) { + if (stun_is_response(&buf)) { - if (stun_is_success_response(&buf)) { + if (stun_is_success_response(&buf)) { - if (stun_is_binding_response(&buf)) { + if (stun_is_binding_response(&buf)) { - addr_set_any(reflexive_addr); - if (stun_attr_get_first_addr(&buf, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, reflexive_addr, NULL) >= 0) { + addr_set_any(reflexive_addr); + if (stun_attr_get_first_addr(&buf, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, reflexive_addr, NULL) >= 0) { - stun_attr_ref sar = stun_attr_get_first_by_type_str(buf.buf, buf.len, STUN_ATTRIBUTE_OTHER_ADDRESS); - if (sar) { - *rfc5780 = 1; - printf("\n========================================\n"); - printf("RFC 5780 response %d\n",++counter); - ioa_addr mapped_addr; - addr_set_any(&mapped_addr); - if (stun_attr_get_first_addr(&buf, STUN_ATTRIBUTE_MAPPED_ADDRESS, &mapped_addr, NULL) >= 0) { - if (!addr_eq(&mapped_addr,reflexive_addr)){ - printf("-= ALG detected! Mapped and XOR-Mapped differ! =-\n"); - addr_debug_print(1, &mapped_addr, "Mapped Address: "); - }else { - printf("No ALG: Mapped and XOR-Mapped is equal.\n"); - } - } else { - printf("Not received mapped address attribute.\n"); - } - stun_attr_get_addr_str((u08bits *) buf.buf, (size_t) buf.len, sar, other_addr, NULL); - sar = stun_attr_get_first_by_type_str(buf.buf, buf.len, STUN_ATTRIBUTE_RESPONSE_ORIGIN); + stun_attr_ref sar = stun_attr_get_first_by_type_str(buf.buf, buf.len, STUN_ATTRIBUTE_OTHER_ADDRESS); if (sar) { - ioa_addr response_origin; - stun_attr_get_addr_str((u08bits *) buf.buf, (size_t) buf.len, sar, &response_origin, NULL); - addr_debug_print(1, &response_origin, "Response origin: "); + *rfc5780 = 1; + printf("\n========================================\n"); + printf("RFC 5780 response %d\n",++counter); + ioa_addr mapped_addr; + addr_set_any(&mapped_addr); + if (stun_attr_get_first_addr(&buf, STUN_ATTRIBUTE_MAPPED_ADDRESS, &mapped_addr, NULL) >= 0) { + if (!addr_eq(&mapped_addr,reflexive_addr)){ + printf("-= ALG detected! Mapped and XOR-Mapped differ! =-\n"); + addr_debug_print(1, &mapped_addr, "Mapped Address: "); + }else { + printf("No ALG: Mapped and XOR-Mapped is equal.\n"); + } + } else { + printf("Not received mapped address attribute.\n"); + } + stun_attr_get_addr_str((u08bits *) buf.buf, (size_t) buf.len, sar, other_addr, NULL); + sar = stun_attr_get_first_by_type_str(buf.buf, buf.len, STUN_ATTRIBUTE_RESPONSE_ORIGIN); + if (sar) { + ioa_addr response_origin; + stun_attr_get_addr_str((u08bits *) buf.buf, (size_t) buf.len, sar, &response_origin, NULL); + addr_debug_print(1, &response_origin, "Response origin: "); + } + addr_debug_print(1, other_addr, "Other addr: "); } - addr_debug_print(1, other_addr, "Other addr: "); + addr_debug_print(1, reflexive_addr, "UDP reflexive addr"); + addr_debug_print(1, local_addr, "Local addr: "); + } else { + printf("Cannot read the response\n"); } - addr_debug_print(1, reflexive_addr, "UDP reflexive addr"); - addr_debug_print(1, local_addr, "Local addr: "); } else { - printf("Cannot read the response\n"); + printf("Wrong type of response\n"); } } else { - printf("Wrong type of response\n"); + int err_code = 0; + u08bits err_msg[1025] = "\0"; + size_t err_msg_size = sizeof(err_msg); + if (stun_is_error_response(&buf, &err_code, err_msg, err_msg_size)) { + printf("The response is an error %d (%s)\n", err_code, (char*) err_msg); + } else { + printf("The response is an unrecognized error\n"); + } } } else { - int err_code = 0; - u08bits err_msg[1025] = "\0"; - size_t err_msg_size = sizeof(err_msg); - if (stun_is_error_response(&buf, &err_code, err_msg, err_msg_size)) { - printf("The response is an error %d (%s)\n", err_code, (char*) err_msg); - } else { - printf("The response is an unrecognized error\n"); - } + printf("The response is not a reponse message\n"); + ret=1; } } else { - printf("The response is not a reponse message\n"); + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { + printf("STUN receive timeout..\n"); + }else{ + printf("The response is not a STUN message\n"); + } ret=1; } - } else { - if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { - printf("STUN receive timeout..\n"); - }else{ - printf("The response is not a STUN message\n"); - } - ret=1; } } + static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780, int change_ip, int change_port, int padding){ + int ret=0; + + udp_fd = socket(remote_addr->ss.sa_family, CLIENT_DGRAM_SOCKET_TYPE, CLIENT_DGRAM_SOCKET_PROTOCOL); + if (udp_fd < 0) + err(-1, NULL); + + if (!addr_any(local_addr)) { + if (addr_bind(udp_fd, local_addr,0,1,UDP_SOCKET) < 0) { + err(-1, NULL); + } + } + + ret=stunclient_send(udp_fd, remote_addr, change_ip, change_port, padding, -1); + ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, port, rfc5780); + + socket_closesocket(udp_fd); + return ret; + } - socket_closesocket(udp_fd); - return ret; -} #endif -//////////////// local definitions ///////////////// + //////////////// local definitions ///////////////// -static char Usage[] = - "Usage: natdiscovery [options] address\n" - "Options:\n" - " -m NAT mapping behavior discovery\n" - " -f NAT filtering behavior discovery\n" - " -c NAT collision behavior discovery\n" - " Requires an alternative IP address (-A)\n" - " -P Add 1500 byte Padding to the behavior discovery\n" + static char Usage[] = + "Usage: natdiscovery [options] address\n" + "Options:\n" + " -m NAT mapping behavior discovery\n" + " -f NAT filtering behavior discovery\n" + " -c NAT collision behavior discovery\n" + " Requires an alternative IP address (-A)\n" + " -P Add 1500 byte Padding to the behavior discovery\n" " Applicable with all except NAT Binding Lifetime discovery\n" " -p STUN server port (Default: 3478)\n" - " -L Local address to use (optional)\n" - " -A Local alrernative address to use\n" - " Used by collision behavior Discovery\n"; + " -L Local address to use (optional)\n" + " -A Local alrernative address to use\n" + " Used by collision behavior Discovery\n"; -////////////////////////////////////////////////// + ////////////////////////////////////////////////// -static void init(ioa_addr *local_addr,ioa_addr *remote_addr,int *local_port,int port, int *rfc5780, char* local_addr_string, char* remote_param) -{ - addr_set_any(local_addr); + static void init(ioa_addr *local_addr,ioa_addr *remote_addr,int *local_port,int port, int *rfc5780, char* local_addr_string, char* remote_param) + { + addr_set_any(local_addr); - if(local_addr_string[0]) { - if(make_ioa_addr((const u08bits*)local_addr_string, 0, local_addr)<0) { - err(-1,NULL); - } - } + if(local_addr_string[0]) { + if(make_ioa_addr((const u08bits*)local_addr_string, 0, local_addr)<0) { + err(-1,NULL); + } + } - *local_port = -1; - *rfc5780 = 0; + *local_port = -1; + *rfc5780 = 0; - if (make_ioa_addr((const u08bits*)remote_param, port, remote_addr) < 0) + if (make_ioa_addr((const u08bits*)remote_param, port, remote_addr) < 0) err(-1, NULL); -} + } -static void discoveryresult(const char *decision){ - printf("\n========================================\n"); - printf("%s",decision); - printf("\n========================================\n"); -} + static void discoveryresult(const char *decision){ + printf("\n========================================\n"); + printf("%s",decision); + printf("\n========================================\n"); + } -int main(int argc, char **argv) -{ - int port = DEFAULT_STUN_PORT; - char local_addr_string[256]="\0"; - char local2_addr_string[256]="\0"; - int c=0; - int mapping = 0; - int filtering = 0; - int collision = 0; - int padding = 0; - int local_port, rfc5780; - ioa_addr other_addr, reflexive_addr, tmp_addr, remote_addr, local_addr, local2_addr; - + int main(int argc, char **argv) + { + int port = DEFAULT_STUN_PORT; + char local_addr_string[256]="\0"; + char local2_addr_string[256]="\0"; + int c=0; + int mapping = 0; + int filtering = 0; + int collision = 0; + int padding = 0; + int local_port, rfc5780; + ioa_addr other_addr, reflexive_addr, tmp_addr, remote_addr, local_addr, local2_addr; - set_logfile("stdout"); - set_system_parameters(0); - - ns_bzero(local_addr_string, sizeof(local_addr_string)); - ns_bzero(local2_addr_string, sizeof(local2_addr_string)); - addr_set_any(&remote_addr); - addr_set_any(&other_addr); - addr_set_any(&reflexive_addr); - addr_set_any(&tmp_addr); - while ((c = getopt(argc, argv, "mfcPp:L:A:")) != -1) { - switch(c) { - case 'm': - mapping=1; - break; - case 'f': - filtering=1; - break; - case 'c': - collision=1; - break; - case 'P': - padding=1; - break; - case 'p': - port = atoi(optarg); - break; - case 'L': - STRCPY(local_addr_string, optarg); - break; - case 'A': - STRCPY(local2_addr_string, optarg); - break; - default: - fprintf(stderr,"%s\n", Usage); - exit(1); - } - } + set_logfile("stdout"); + set_system_parameters(0); - if(optind>=argc) { - fprintf(stderr, "%s\n", Usage); - exit(-1); - } - - if(collision && local2_addr_string == '\0'){ - fprintf(stderr, "Use \"-A\" to add an Alternative local IP address.\n"); - fprintf(stderr, "It is mandatory with \"-c\" collision behavior detection..\n"); - exit(-1); - } + ns_bzero(local_addr_string, sizeof(local_addr_string)); + ns_bzero(local2_addr_string, sizeof(local2_addr_string)); + addr_set_any(&remote_addr); + addr_set_any(&other_addr); + addr_set_any(&reflexive_addr); + addr_set_any(&tmp_addr); - init(&local_addr, &remote_addr, &local_port, port, &rfc5780, local_addr_string, argv[optind]); - - if(mapping) { - run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,padding); - if (addr_eq(&local_addr,&reflexive_addr)){ - discoveryresult("No NAT! (Endpoint Independent Mapping)"); + while ((c = getopt(argc, argv, "mfcPp:L:A:")) != -1) { + switch(c) { + case 'm': + mapping=1; + break; + case 'f': + filtering=1; + break; + case 'c': + collision=1; + break; + case 'P': + padding=1; + break; + case 'p': + port = atoi(optarg); + break; + case 'L': + STRCPY(local_addr_string, optarg); + break; + case 'A': + STRCPY(local2_addr_string, optarg); + break; + default: + fprintf(stderr,"%s\n", Usage); + exit(1); + } } - if(rfc5780) { - if(!addr_any(&other_addr)){ - addr_cpy(&tmp_addr, &reflexive_addr); - addr_cpy(&remote_addr, &other_addr); - addr_set_port(&remote_addr, port); + if(optind>=argc) { + fprintf(stderr, "%s\n", Usage); + exit(-1); + } - run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,padding); + if(collision && local2_addr_string == '\0'){ + fprintf(stderr, "Use \"-A\" to add an Alternative local IP address.\n"); + fprintf(stderr, "It is mandatory with \"-c\" collision behavior detection..\n"); + exit(-1); + } - if(addr_eq(&tmp_addr,&reflexive_addr)){ - discoveryresult("NAT with Enpoint Independent Mapping!"); - } else { + init(&local_addr, &remote_addr, &local_port, port, &rfc5780, local_addr_string, argv[optind]); + + if(mapping) { + run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); + if (addr_eq(&local_addr,&reflexive_addr)){ + discoveryresult("No NAT! (Endpoint Independent Mapping)"); + } + if(rfc5780) { + if(!addr_any(&other_addr)){ addr_cpy(&tmp_addr, &reflexive_addr); + addr_cpy(&remote_addr, &other_addr); - run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,padding); + addr_set_port(&remote_addr, port); + + run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); + if(addr_eq(&tmp_addr,&reflexive_addr)){ - discoveryresult("NAT with Address Dependent Mapping!"); + discoveryresult("NAT with Enpoint Independent Mapping!"); } else { - discoveryresult("NAT with Address and Port Dependent Mapping!"); + addr_cpy(&tmp_addr, &reflexive_addr); + addr_cpy(&remote_addr, &other_addr); + run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); + if(addr_eq(&tmp_addr,&reflexive_addr)){ + discoveryresult("NAT with Address Dependent Mapping!"); + } else { + discoveryresult("NAT with Address and Port Dependent Mapping!"); + } } } - } - } - } - - init(&local_addr, &remote_addr, &local_port, port, &rfc5780, local_addr_string, argv[optind]); - - if(filtering) { - run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,padding); - if(addr_eq(&local_addr, &reflexive_addr)){ - discoveryresult("No NAT! (Endpoint Independent Mapping)"); + } } - if(rfc5780) { - if(!addr_any(&other_addr)){ - int res=0; - res=run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,1,1,padding); - if (!res) { - discoveryresult("NAT with Enpoint Independent Filtering!"); - } else { - res=0; - res=run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,1,padding); - if(!res){ - discoveryresult("NAT with Address Dependent Filtering!"); + + init(&local_addr, &remote_addr, &local_port, port, &rfc5780, local_addr_string, argv[optind]); + + if(filtering) { + run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); + if(addr_eq(&local_addr, &reflexive_addr)){ + discoveryresult("No NAT! (Endpoint Independent Mapping)"); + } + if(rfc5780) { + if(!addr_any(&other_addr)){ + int res=0; + res=run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,1,1,padding); + if (!res) { + discoveryresult("NAT with Enpoint Independent Filtering!"); } else { - discoveryresult("NAT with Address and Port Dependent Filtering!"); + res=0; + res=run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,1,padding); + if(!res){ + discoveryresult("NAT with Address Dependent Filtering!"); + } else { + discoveryresult("NAT with Address and Port Dependent Filtering!"); + } } } - } - } - } + } + } - init(&local_addr, &remote_addr, &local_port, port, &rfc5780, local_addr_string, argv[optind]); + init(&local_addr, &remote_addr, &local_port, port, &rfc5780, local_addr_string, argv[optind]); - if(collision) { - addr_set_any(&local2_addr); + if(collision) { + addr_set_any(&local2_addr); - if(local2_addr_string[0]) { - if(make_ioa_addr((const u08bits*)local2_addr_string, 0, &local2_addr)<0) { - err(-1,NULL); - } - } + if(local2_addr_string[0]) { + if(make_ioa_addr((const u08bits*)local2_addr_string, 0, &local2_addr)<0) { + err(-1,NULL); + } + } - run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,padding); - addr_set_port(&local2_addr,addr_get_port(&local_addr)); - run_stunclient(&local2_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,padding); - } + run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); + addr_set_port(&local2_addr,addr_get_port(&local_addr)); + run_stunclient(&local2_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); + } - if (!filtering && !mapping && !collision) { - printf("Please use either -f or -c or -m parameter for Filtering or Mapping behavior discovery.\n"); - } - socket_closesocket(udp_fd); + if (!filtering && !mapping && !collision) { + printf("Please use either -f or -c or -m parameter for Filtering or Mapping behavior discovery.\n"); + } + socket_closesocket(udp_fd); + socket_closesocket(udp_fd2); - return 0; -} + return 0; + } From b86be4e0062944d0bcaead8da36d487466035f59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9sz=C3=A1ros=20Mih=C3=A1ly?= Date: Wed, 27 Sep 2017 21:52:36 +0200 Subject: [PATCH 07/17] rephrase --- src/apps/natdiscovery/natdiscovery.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/natdiscovery/natdiscovery.c b/src/apps/natdiscovery/natdiscovery.c index a33f5f6..84d8df2 100644 --- a/src/apps/natdiscovery/natdiscovery.c +++ b/src/apps/natdiscovery/natdiscovery.c @@ -190,7 +190,7 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex printf("-= ALG detected! Mapped and XOR-Mapped differ! =-\n"); addr_debug_print(1, &mapped_addr, "Mapped Address: "); } else { - printf("No ALG: Mapped and XOR-Mapped is equal.\n"); + printf("No ALG: Mapped == XOR-Mapped\n"); } } else { printf("Not received mapped address attribute!\n"); @@ -344,7 +344,7 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex printf("-= ALG detected! Mapped and XOR-Mapped differ! =-\n"); addr_debug_print(1, &mapped_addr, "Mapped Address: "); }else { - printf("No ALG: Mapped and XOR-Mapped is equal.\n"); + printf("No ALG: Mapped == XOR-Mapped\n"); } } else { printf("Not received mapped address attribute.\n"); From 3a99678ac10e76c7052299bd25133cde4ad279fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9sz=C3=A1ros=20Mih=C3=A1ly?= Date: Thu, 28 Sep 2017 00:31:28 +0200 Subject: [PATCH 08/17] Add hairpinning check --- src/apps/natdiscovery/natdiscovery.c | 219 ++++++++++++++++++++------- 1 file changed, 162 insertions(+), 57 deletions(-) diff --git a/src/apps/natdiscovery/natdiscovery.c b/src/apps/natdiscovery/natdiscovery.c index 84d8df2..cd7ae17 100644 --- a/src/apps/natdiscovery/natdiscovery.c +++ b/src/apps/natdiscovery/natdiscovery.c @@ -122,6 +122,7 @@ static int stunclient_send(int sockfd, ioa_addr *remote_addr, int change_ip, int } + return ret; } @@ -164,7 +165,6 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex turn::StunMsgResponse res(buf.buf, sizeof(buf.buf), (size_t)buf.len, true); if (res.isCommand()) { - if(res.isSuccess()) { if (res.isBindingResponse()) { @@ -180,13 +180,13 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex *rfc5780 = 1; printf("\n========================================\n"); printf("RFC 5780 response %d\n",++counter); - turn::StunAttrIterator iter0(res,STUN_ATTRIBUTE_MAPPED_ADDRESS); - if (!iter0.eof()) { + turn::StunAttrIterator iter2(res,STUN_ATTRIBUTE_MAPPED_ADDRESS); + if (!iter2.eof()) { ioa_addr mapped_addr; - addr_set_any(mapped_addr); - turn::StunAttrAddr addr0(iter0); - addr0.getAddr(mapped_addr); - if (!addr_eq(mapped_addr,reflexive_addr)){ + addr_set_any(&mapped_addr); + turn::StunAttrAddr addr2(iter2); + addr2.getAddr(mapped_addr); + if (!addr_eq(&mapped_addr,reflexive_addr)){ printf("-= ALG detected! Mapped and XOR-Mapped differ! =-\n"); addr_debug_print(1, &mapped_addr, "Mapped Address: "); } else { @@ -196,44 +196,67 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex printf("Not received mapped address attribute!\n"); } turn::StunAttrAddr addr1(iter1); addr1.getAddr(*other_addr); - turn::StunAttrIterator iter2(res,STUN_ATTRIBUTE_RESPONSE_ORIGIN); - if (!iter2.eof()) { + turn::StunAttrIterator iter3(res,STUN_ATTRIBUTE_RESPONSE_ORIGIN); + if (!iter3.eof()) { ioa_addr response_origin; - turn::StunAttrAddr addr2(iter2); - addr2.getAddr(response_origin); + turn::StunAttrAddr addr3(iter3); + addr3.getAddr(response_origin); addr_debug_print(1, &response_origin, "Response origin: "); - - - addr_debug_print(1, other_addr, "Other addr: "); } - addr_debug_print(1, reflexive_addr, "UDP reflexive addr"); - addr_debug_print(1, local_addr, "Local addr: "); - } else { - printf("Cannot read the response\n"); + addr_debug_print(1, other_addr, "Other addr: "); } + addr_debug_print(1, reflexive_addr, "UDP reflexive addr"); + addr_debug_print(1, local_addr, "Local addr: "); } else { - printf("Wrong type of response\n"); + printf("Cannot read the response\n"); } } else { - int err_code = res.getError(); - std::string reason = res.getReason(); - - printf("The response is an error %d (%s)\n", err_code, reason.c_str()); + printf("Wrong type of response\n"); } } else { - printf("The response is not a reponse message\n"); + int err_code = res.getError(); + std::string reason = res.getReason(); + + printf("The response is an error %d (%s)\n", err_code, reason.c_str()); } - } catch(...) { + } else { + printf("The response is not a reponse message\n"); + } + } catch(...) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { printf("STUN receive timeout..\n"); }else{ - printf("The response is not a well formed STUN message\n"); + if (isRequest(buf.buf,(size_t)buf.len)) { + printf("Received a request (maybe a successful hairpinning)\n"); + return ret; + } else { + printf("The response is not a well formed STUN message\n"); + } } ret=1; } } + + return ret; } + + static int init_socket(int *socketfd, ioa_addr *local_addr, ioa_addr *remote_addr){ + int ret=0; + + *socketfd = socket(remote_addr->ss.sa_family, SOCK_DGRAM, 0); + if (udp_fd < 0) + err(-1, NULL); + + if (!addr_any(local_addr)) { + if (addr_bind(*socketfd, local_addr,0,1,UDP_SOCKET) < 0) + err(-1, NULL); + } + + return ret; + } + + static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780, int change_ip, int change_port, int padding){ int ret=0; @@ -253,22 +276,48 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex return ret; } + + static int run_stunclient_hairpinning(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780, int change_ip, int change_port, int padding){ + int ret=0; + + init_socket(&udp_fd,local_addr,remote_addr); + + ret=stunclient_send(udp_fd, remote_addr, change_ip, change_port, padding, -1); + ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, port, rfc5780); + + + addr_cpy(remote_addr,reflexive_addr); + addr_set_port(local_addr, 0); + + init_socket(&udp_fd2,local_addr,remote_addr); + + ret=stunclient_send(udp_fd2, remote_addr, change_ip, change_port, padding, -1); + ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, port, rfc5780); + + if(ret){ + ret=stunclient_receive(udp_fd2, local_addr, reflexive_addr, other_addr, port, rfc5780); + } + close(udp_fd); + close(udp_fd2); + + return ret; + } + #else - static int stunclient_send(int sockfd, ioa_addr *remote_addr, int change_ip, int change_port, int padding, int response_port){ + static int stunclient_send(stun_buffer *buf, int sockfd, ioa_addr *remote_addr, int change_ip, int change_port, int padding, int response_port){ int ret=0; - stun_buffer buf; - stun_prepare_binding_request(&buf); + stun_prepare_binding_request(buf); if (response_port >= 0) { - stun_attr_add_response_port_str((u08bits*) (buf.buf), (size_t*) &(buf.len), (u16bits) response_port); + stun_attr_add_response_port_str((u08bits*) (buf->buf), (size_t*) &(buf->len), (u16bits) response_port); } if (change_ip || change_port) { - stun_attr_add_change_request_str((u08bits*) buf.buf, (size_t*) &(buf.len), change_ip, change_port); + stun_attr_add_change_request_str((u08bits*) buf->buf, (size_t*) &(buf->len), change_ip, change_port); } if (padding) { - if(stun_attr_add_padding_str((u08bits*) buf.buf, (size_t*) &(buf.len), 1500)<0) { + if(stun_attr_add_padding_str((u08bits*) buf->buf, (size_t*) &(buf->len), 1500)<0) { printf("%s: ERROR: Cannot add padding\n",__FUNCTION__); } } @@ -278,15 +327,19 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex int slen = get_ioa_addr_len(remote_addr); do { - len = sendto(sockfd, buf.buf, buf.len, 0, (struct sockaddr*) remote_addr, (socklen_t) slen); + len = sendto(sockfd, buf->buf, buf->len, 0, (struct sockaddr*) remote_addr, (socklen_t) slen); } while (len < 0 && ((errno == EINTR) || (errno == ENOBUFS) || (errno == EAGAIN))); if (len < 0) err(-1, NULL); } + + return ret; } - static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780){ + + + static int stunclient_receive(stun_buffer *buf, int sockfd, ioa_addr *local_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780){ int ret=0; if (addr_get_from_sock(sockfd, local_addr) < 0) { @@ -298,9 +351,9 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex { int len = 0; - u08bits *ptr = buf.buf; + u08bits *ptr = buf->buf; int recvd = 0; - const int to_recv = sizeof(buf.buf); + const int to_recv = sizeof(buf->buf); struct timeval tv; tv.tv_sec = 3; /* 3 Secs Timeout */ @@ -319,27 +372,27 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex if (recvd > 0) len = recvd; - buf.len = len; + buf->len = len; - if (stun_is_command_message(&buf)) { + if (stun_is_command_message(buf)) { - if (stun_is_response(&buf)) { + if (stun_is_response(buf)) { - if (stun_is_success_response(&buf)) { + if (stun_is_success_response(buf)) { - if (stun_is_binding_response(&buf)) { + if (stun_is_binding_response(buf)) { addr_set_any(reflexive_addr); - if (stun_attr_get_first_addr(&buf, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, reflexive_addr, NULL) >= 0) { + if (stun_attr_get_first_addr(buf, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, reflexive_addr, NULL) >= 0) { - stun_attr_ref sar = stun_attr_get_first_by_type_str(buf.buf, buf.len, STUN_ATTRIBUTE_OTHER_ADDRESS); + stun_attr_ref sar = stun_attr_get_first_by_type_str(buf->buf, buf->len, STUN_ATTRIBUTE_OTHER_ADDRESS); if (sar) { *rfc5780 = 1; printf("\n========================================\n"); printf("RFC 5780 response %d\n",++counter); ioa_addr mapped_addr; addr_set_any(&mapped_addr); - if (stun_attr_get_first_addr(&buf, STUN_ATTRIBUTE_MAPPED_ADDRESS, &mapped_addr, NULL) >= 0) { + if (stun_attr_get_first_addr(buf, STUN_ATTRIBUTE_MAPPED_ADDRESS, &mapped_addr, NULL) >= 0) { if (!addr_eq(&mapped_addr,reflexive_addr)){ printf("-= ALG detected! Mapped and XOR-Mapped differ! =-\n"); addr_debug_print(1, &mapped_addr, "Mapped Address: "); @@ -349,11 +402,11 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex } else { printf("Not received mapped address attribute.\n"); } - stun_attr_get_addr_str((u08bits *) buf.buf, (size_t) buf.len, sar, other_addr, NULL); - sar = stun_attr_get_first_by_type_str(buf.buf, buf.len, STUN_ATTRIBUTE_RESPONSE_ORIGIN); + stun_attr_get_addr_str((u08bits *) buf->buf, (size_t) buf->len, sar, other_addr, NULL); + sar = stun_attr_get_first_by_type_str(buf->buf, buf->len, STUN_ATTRIBUTE_RESPONSE_ORIGIN); if (sar) { ioa_addr response_origin; - stun_attr_get_addr_str((u08bits *) buf.buf, (size_t) buf.len, sar, &response_origin, NULL); + stun_attr_get_addr_str((u08bits *) buf->buf, (size_t) buf->len, sar, &response_origin, NULL); addr_debug_print(1, &response_origin, "Response origin: "); } addr_debug_print(1, other_addr, "Other addr: "); @@ -370,12 +423,14 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex int err_code = 0; u08bits err_msg[1025] = "\0"; size_t err_msg_size = sizeof(err_msg); - if (stun_is_error_response(&buf, &err_code, err_msg, err_msg_size)) { + if (stun_is_error_response(buf, &err_code, err_msg, err_msg_size)) { printf("The response is an error %d (%s)\n", err_code, (char*) err_msg); } else { printf("The response is an unrecognized error\n"); } } + } else if (stun_is_request(buf)) { + printf("Received a request (maybe a successful hairpinning)\n"); } else { printf("The response is not a reponse message\n"); ret=1; @@ -389,24 +444,68 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex ret=1; } } + + return ret; } - static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780, int change_ip, int change_port, int padding){ + + + static int init_socket(int *socketfd, ioa_addr *local_addr, ioa_addr *remote_addr){ int ret=0; - udp_fd = socket(remote_addr->ss.sa_family, CLIENT_DGRAM_SOCKET_TYPE, CLIENT_DGRAM_SOCKET_PROTOCOL); + *socketfd = socket(remote_addr->ss.sa_family, CLIENT_DGRAM_SOCKET_TYPE, CLIENT_DGRAM_SOCKET_PROTOCOL); if (udp_fd < 0) err(-1, NULL); if (!addr_any(local_addr)) { - if (addr_bind(udp_fd, local_addr,0,1,UDP_SOCKET) < 0) { + if (addr_bind(*socketfd, local_addr,0,1,UDP_SOCKET) < 0) { err(-1, NULL); } } - ret=stunclient_send(udp_fd, remote_addr, change_ip, change_port, padding, -1); - ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, port, rfc5780); + return ret; + } + + + static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780, int change_ip, int change_port, int padding){ + int ret=0; + stun_buffer buf; + + init_socket(&udp_fd,local_addr,remote_addr); + + ret=stunclient_send(&buf,udp_fd, remote_addr, change_ip, change_port, padding, -1); + ret=stunclient_receive(&buf,udp_fd, local_addr, reflexive_addr, other_addr, port, rfc5780); socket_closesocket(udp_fd); + + return ret; + } + + static int run_stunclient_hairpinning(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780, int change_ip, int change_port, int padding){ + int ret=0; + stun_buffer buf; + stun_buffer buf2; + + init_socket(&udp_fd,local_addr,remote_addr); + + ret=stunclient_send(&buf, udp_fd, remote_addr, change_ip, change_port, padding, -1); + ret=stunclient_receive(&buf, udp_fd, local_addr, reflexive_addr, other_addr, port, rfc5780); + + + addr_cpy(remote_addr,reflexive_addr); + addr_set_port(local_addr, 0); + + init_socket(&udp_fd2,local_addr,remote_addr); + + ret=stunclient_send(&buf2, udp_fd2, remote_addr, change_ip, change_port, padding, -1); + ret=stunclient_receive(&buf, udp_fd, local_addr, reflexive_addr, other_addr, port, rfc5780); + + if(ret){ + ret=stunclient_receive(&buf2, udp_fd2, local_addr, reflexive_addr, other_addr, port, rfc5780); + } + + socket_closesocket(udp_fd); + socket_closesocket(udp_fd2); + return ret; } @@ -463,6 +562,7 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex int filtering = 0; int collision = 0; int padding = 0; + int hairpinning = 0; int local_port, rfc5780; ioa_addr other_addr, reflexive_addr, tmp_addr, remote_addr, local_addr, local2_addr; @@ -477,7 +577,7 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex addr_set_any(&reflexive_addr); addr_set_any(&tmp_addr); - while ((c = getopt(argc, argv, "mfcPp:L:A:")) != -1) { + while ((c = getopt(argc, argv, "mfcPHp:L:A:")) != -1) { switch(c) { case 'm': mapping=1; @@ -488,6 +588,9 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex case 'c': collision=1; break; + case 'H': + hairpinning=1; + break; case 'P': padding=1; break; @@ -518,7 +621,9 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex } init(&local_addr, &remote_addr, &local_port, port, &rfc5780, local_addr_string, argv[optind]); - + if(hairpinning) { + run_stunclient_hairpinning(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); + } if(mapping) { run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); if (addr_eq(&local_addr,&reflexive_addr)){ @@ -591,8 +696,8 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex run_stunclient(&local2_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); } - if (!filtering && !mapping && !collision) { - printf("Please use either -f or -c or -m parameter for Filtering or Mapping behavior discovery.\n"); + if (!filtering && !mapping && !collision && !hairpinning) { + printf("Please use either -f or -c or -m or -H parameter for Filtering or Mapping behavior discovery.\n"); } socket_closesocket(udp_fd); socket_closesocket(udp_fd2); From 56da0bfee5f2294cef80b0077b5315be76f1c406 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9sz=C3=A1ros=20Mih=C3=A1ly?= Date: Thu, 28 Sep 2017 00:35:38 +0200 Subject: [PATCH 09/17] Add hairpinning natdiscovery to README and man --- README.turnutils | 162 ++++++++++++++++++++++--------------------- man/man1/turnutils.1 | 100 +++++++++++++------------- 2 files changed, 135 insertions(+), 127 deletions(-) diff --git a/README.turnutils b/README.turnutils index ae9bda4..7552b6e 100644 --- a/README.turnutils +++ b/README.turnutils @@ -1,40 +1,40 @@ GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used -for testing and for setting up the TURN server. - -1. turnutils_uclient: emulates multiple UDP,TCP,TLS or DTLS clients. +for testing and for setting up the TURN server. + +1. turnutils_uclient: emulates multiple UDP,TCP,TLS or DTLS clients. (this program is provided for the testing purposes only !) -The compiled binary image of this program is located in bin/ +The compiled binary image of this program is located in bin/ sub-directory. -2. turnutils_peer: a simple stateless UDP-only "echo" server, -to be used as the final server in relay pattern ("peer"). For every incoming +2. turnutils_peer: a simple stateless UDP-only "echo" server, +to be used as the final server in relay pattern ("peer"). For every incoming UDP packet, it simply echoes it back. -(this program is provided for the testing purposes only !) -When the test clients are communicating in the client-to-client manner -(when the "turnutils_uclient" program is used with "-y" option) then the +(this program is provided for the testing purposes only !) +When the test clients are communicating in the client-to-client manner +(when the "turnutils_uclient" program is used with "-y" option) then the turnutils_peer is not needed. - + The compiled binary image of this program is located in bin/ subdirectory. - -3. turnutils_stunclient: a simple STUN client example. + +3. turnutils_stunclient: a simple STUN client example. The compiled binary image of this program is located in bin/ subdirectory. - -4. turnutils_rfc5769check: a utility that checks the correctness of the + +4. turnutils_rfc5769check: a utility that checks the correctness of the STUN/TURN protocol implementation. This utility is used only for the compilation check procedure, it is not copied to the installation destination. -In the "examples/scripts" subdirectory, you will find the examples of command lines to be used +In the "examples/scripts" subdirectory, you will find the examples of command lines to be used to run the programs. The scripts are meant to be run from examples/ subdirectory, for example: $ cd examples $ ./scripts/secure_relay.sh -5. turnutils_natdiscovery: a utility that provides NAT behavior discovery -according RFC5780. This utility discovers the actual NAT Mapping and Filtering -behavior. Be aweare that at least two different listening IP addresses should +5. turnutils_natdiscovery: a utility that provides NAT behavior discovery +according RFC5780. This utility discovers the actual NAT Mapping and Filtering +behavior. Be aweare that at least two different listening IP addresses should be configured to be able to work properly! 6. turnutils_oauth: a utility that provides OAuth access_token @@ -49,34 +49,34 @@ script in examples/scripts/oauth.sh. ===================================== - + NAME - + turnutils_uclient - this client emulation application is supplied for the test purposes only. - - SYNOPSIS + + SYNOPSIS $ turnutils_uclient [-tTSvsyhcxg] [options] - + DESCRIPTION - -It was designed to simulate multiple clients. It uses asynch IO API in -libevent to handle multiple clients. A client connects to the relay, -negotiates the session, and sends multiple (configured number) messages to the server (relay), -expecting the same number of replies. The length of the messages is configurable. -The message is an arbitrary octet stream. + +It was designed to simulate multiple clients. It uses asynch IO API in +libevent to handle multiple clients. A client connects to the relay, +negotiates the session, and sends multiple (configured number) messages to the server (relay), +expecting the same number of replies. The length of the messages is configurable. +The message is an arbitrary octet stream. The number of the messages to send is configurable. -Flags: +Flags: -t Use TCP for communications between client and TURN server (default is UDP). -b Use SCTP for communications between client and TURN server (default is UDP). --T Use TCP for the relay transport (default - UDP). Implies options -t, -y, -c, +-T Use TCP for the relay transport (default - UDP). Implies options -t, -y, -c, and ignores flags and options -s, -e, -r and -g. Can be used together with -b. - + -P Passive TCP (RFC6062 with active peer). Implies -T. -S Secure SSL connection: SSL/TLS for TCP, DTLS for UDP, TLS/SCTP for SCTP. @@ -87,11 +87,11 @@ Flags: -s Use "Send" method in TURN; by default, it uses TURN Channels. --y Use client-to-client connections: +-y Use client-to-client connections: RTP/RTCP pair of channels to another RTP/RTCP pair of channels. with this option the turnutils_peer application is not used, as the allocated relay endpoints are talking to each other. - + -h Hang on indefinitely after the last sent packet. -c Do not create rtcp connections. @@ -109,12 +109,12 @@ Flags: -R do negative protocol tests. -O DOS attack mode. - + -M Use TURN ICE Mobility. -I Do not set permissions on TURN relay endpoints (for testing the non-standard server relay functionality). - + -G Generate extra requests (create permissions, channel bind). -B Random disconnect after a few initial packets. @@ -123,7 +123,7 @@ Flags: -J Use oAuth with default test key kid='north'. -Options with required values: +Options with required values: -l Message length (Default: 100 Bytes). @@ -159,7 +159,7 @@ Options with required values: table in the database if dynamic, or the static-auth-secret value set in the configuration file if using static. --C This is the timestamp/username separator symbol (character) in +-C This is the timestamp/username separator symbol (character) in TURN REST API. The default value is :. -F Cipher suite for TLS/DTLS. Default value is DEFAULT. @@ -171,23 +171,23 @@ Options with required values: See the examples in the "examples/scripts" directory. ====================================== - + NAME - -turnutils_peer - a simple UDP-only echo backend server. - + +turnutils_peer - a simple UDP-only echo backend server. + SYNOPSIS $ turnutils_peer [-v] [options] - + DESCRIPTION - + This application is used for the test purposes only, as a peer for the turnutils_uclient application. -Options with required values: +Options with required values: -p Listening UDP port (Default: 3480). - + -d Listening interface device (optional) -L Listening address of turnutils_peer server. Multiple listening addresses can be used, IPv4 and IPv6. @@ -198,50 +198,50 @@ If no listener address(es) defined, then it listens on all IPv4 and IPv6 address ======================================== NAME - -turnutils_stunclient - a basic STUN client. - + +turnutils_stunclient - a basic STUN client. + SYNOPSIS $ turnutils_stunclient [options] - + DESCRIPTION - + It sends a "new" STUN RFC 5389 request (over UDP) and shows the reply information. -Options with required values: +Options with required values: -p STUN server port (Default: 3478). - + -L Local address to use (optional). -f Force RFC 5780 processing. -The turnutils_stunclient program checks the results of the first request, -and if it finds that the STUN server supports RFC 5780 -(the binding response reveals that) then the turnutils_stunclient makes a couple more +The turnutils_stunclient program checks the results of the first request, +and if it finds that the STUN server supports RFC 5780 +(the binding response reveals that) then the turnutils_stunclient makes a couple more requests with different parameters, to demonstrate the NAT discovery capabilities. This utility does not support the "old" "classic" STUN protocol (RFC 3489). - + ===================================== NAME - -turnutils_rfc5769check - a utility that tests the correctness of STUN protocol implementation. - + +turnutils_rfc5769check - a utility that tests the correctness of STUN protocol implementation. + SYNOPSIS - + $ turnutils_rfc5769check - + DESCRIPTION -turnutils_rfc5769check tests the correctness of STUN protocol implementation -against the test vectors predefined in RFC 5769 and prints the results of the +turnutils_rfc5769check tests the correctness of STUN protocol implementation +against the test vectors predefined in RFC 5769 and prints the results of the tests on the screen. This utility is used only for the compilation check procedure, it is not copied to the installation destination. - -Usage: + +Usage: $ turnutils_rfc5769check @@ -249,7 +249,7 @@ $ turnutils_rfc5769check NAME -turnutils_natdiscovery - a utility that discovers NAT mapping and filtering +turnutils_natdiscovery - a utility that discovers NAT mapping and filtering behavior according RFC5780. SYNOPSIS @@ -258,13 +258,13 @@ $ turnutils_natdiscovery [options] DESCRIPTION -turnutils_natdiscovery discovers the NAT Mapping and Filtering behavior, to -determine if that NAT is currently using Endpoint-Independent, -Address-Dependent, or Address and Port-Dependent Mapping and/or to determine if -that NAT is currently using Endpoint-Independent, Address-Dependent, or Address -and Port-Dependent Filtering. +turnutils_natdiscovery discovers the NAT Mapping and Filtering behavior, to +determine if that NAT is currently using Endpoint-Independent, +Address-Dependent, or Address and Port-Dependent Mapping and/or to determine if +that NAT is currently using Endpoint-Independent, Address-Dependent, or Address +and Port-Dependent Filtering. -Use either -m, -f, -c flag to discover NAT behavior. +Use either -m, -f, -c, -H flag to discover NAT behavior. Flags: @@ -274,6 +274,8 @@ Flags: -c NAT collision behavior discovery +-H NAT hairpinning behavior discovery + Options with required values: -p STUN server port (Default: 3478) @@ -356,7 +358,7 @@ Usage: $ turnutils_natdiscovery =================================== - + DOCS After installation, run the command: @@ -402,7 +404,7 @@ new STUN RFC 5389 TURN RFC 5766 TURN-TCP extension RFC 6062 - + TURN IPv6 extension RFC 6156 STUN/TURN test vectors RFC 5769 @@ -448,15 +450,15 @@ SEE ALSO Erik Johnston Roman Lisagor - + Vladimir Tsanev - + Po-sheng Lin - + Peter Dunkley - + Mutsutoshi Yoshimoto - + Federico Pinna Bradley T. Hughes diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index af25b7d..371397a 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -3,39 +3,39 @@ .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used -for testing and for setting up the TURN server. +for testing and for setting up the TURN server. .TP .B 1. -\fIturnutils_uclient\fP: emulates multiple UDP,TCP,TLS or DTLS clients. +\fIturnutils_uclient\fP: emulates multiple UDP,TCP,TLS or DTLS clients. (this program is provided for the testing purposes only !) -The compiled binary image of this program is located in bin/ +The compiled binary image of this program is located in bin/ sub\-directory. .TP .B 2. -\fIturnutils_peer\fP: a simple stateless UDP\-only "echo" server, -to be used as the final server in relay pattern ("peer"). For every incoming +\fIturnutils_peer\fP: a simple stateless UDP\-only "echo" server, +to be used as the final server in relay pattern ("peer"). For every incoming UDP packet, it simply echoes it back. -(this program is provided for the testing purposes only !) -When the test clients are communicating in the client\-to\-client manner -(when the "\fIturnutils_uclient\fP" program is used with "\fB\-y\fP" option) then the +(this program is provided for the testing purposes only !) +When the test clients are communicating in the client\-to\-client manner +(when the "\fIturnutils_uclient\fP" program is used with "\fB\-y\fP" option) then the \fIturnutils_peer\fP is not needed. .PP The compiled binary image of this program is located in bin/ subdirectory. .TP .B 3. -\fIturnutils_stunclient\fP: a simple STUN client example. +\fIturnutils_stunclient\fP: a simple STUN client example. The compiled binary image of this program is located in bin/ subdirectory. .TP .B 4. -\fIturnutils_rfc5769check\fP: a utility that checks the correctness of the +\fIturnutils_rfc5769check\fP: a utility that checks the correctness of the STUN/TURN protocol implementation. This utility is used only for the compilation check procedure, it is not copied to the installation destination. .PP -In the "examples/scripts" subdirectory, you will find the examples of command lines to be used +In the "examples/scripts" subdirectory, you will find the examples of command lines to be used to run the programs. The scripts are meant to be run from examples/ subdirectory, for example: .PP $ cd examples @@ -44,9 +44,9 @@ $ ./scripts/secure_relay.sh .TP .B 5. -\fIturnutils_natdiscovery\fP: a utility that provides NAT behavior discovery -according RFC5780. This utility discovers the actual NAT Mapping and Filtering -behavior. Be aweare that at least two different listening IP addresses should +\fIturnutils_natdiscovery\fP: a utility that provides NAT behavior discovery +according RFC5780. This utility discovers the actual NAT Mapping and Filtering +behavior. Be aweare that at least two different listening IP addresses should be configured to be able to work properly! .TP .B @@ -69,19 +69,25 @@ script in examples/scripts/oauth.sh. \fB \fBturnutils_uclient \fP\- this client emulation application is supplied for the test purposes only. \fB -.SS SYNOPSIS +.SS SYNOPSIS +.nf +.fam C -$ \fIturnutils_uclient\fP [\fB\-tTSvsyhcxg\fP] [options] +$ \fIturnutils_uclient\fP [\fB\-tTSvsyhcxg\fP] [\fIoptions\fP] + +.fam T +.fi +.fam T +.fi .SS DESCRIPTION -It was designed to simulate multiple clients. It uses asynch IO API in -libevent to handle multiple clients. A client connects to the relay, -negotiates the session, and sends multiple (configured number) messages to the server (relay), -expecting the same number of replies. The length of the messages is configurable. -The message is an arbitrary octet stream. +It was designed to simulate multiple clients. It uses asynch IO API in +libevent to handle multiple clients. A client connects to the relay, +negotiates the session, and sends multiple (configured number) messages to the server (relay), +expecting the same number of replies. The length of the messages is configurable. +The message is an arbitrary octet stream. The number of the messages to send is configurable. -.TP -.B +.PP Flags: .TP .B @@ -94,8 +100,8 @@ Use SCTP for communications between client and TURN server (default is UDP). .TP .B \fB\-T\fP -Use TCP for the relay transport (default \- UDP). Implies options \fB\-t\fP, \fB\-y\fP, \fB\-c\fP, -and ignores flags and options \fB\-s\fP, \fB\-e\fP, \fB\-r\fP and \fB\-g\fP. Can be used together +Use TCP for the relay transport (default \- UDP). Implies \fIoptions\fP \fB\-t\fP, \fB\-y\fP, \fB\-c\fP, +and ignores flags and \fIoptions\fP \fB\-s\fP, \fB\-e\fP, \fB\-r\fP and \fB\-g\fP. Can be used together with \fB\-b\fP. .TP .B @@ -120,7 +126,7 @@ Use "Send" method in TURN; by default, it uses TURN Channels. .TP .B \fB\-y\fP -Use client\-to\-client connections: +Use client\-to\-client connections: RTP/RTCP pair of channels to another RTP/RTCP pair of channels. with this option the \fIturnutils_peer\fP application is not used, as the allocated relay endpoints are talking to each other. @@ -185,8 +191,7 @@ Dual allocation (SSODA). Implies \fB\-c\fP option. .B \fB\-J\fP Use oAuth with default test key kid='north'. -.TP -.B +.PP Options with required values: .TP .B @@ -224,7 +229,7 @@ Local IP address (optional). .TP .B \fB\-m\fP -Number of clients (Default: 1, 2 or 4, depending on options). +Number of clients (Default: 1, 2 or 4, depending on \fIoptions\fP). .TP .B \fB\-e\fP @@ -255,7 +260,7 @@ value set in the configuration file if using static. .TP .B \fB\-C\fP -This is the timestamp/username separator symbol (character) in +This is the timestamp/username separator symbol (character) in TURN REST API. The default value is :. .TP .B @@ -290,8 +295,7 @@ $ \fIturnutils_peer\fP [\fB\-v\fP] [\fIoptions\fP] .SS DESCRIPTION This application is used for the test purposes only, as a peer for the \fIturnutils_uclient\fP application. -.TP -.B +.PP Options with required values: .TP .B @@ -329,8 +333,7 @@ $ \fIturnutils_stunclient\fP [\fIoptions\fP] .SS DESCRIPTION It sends a "new" STUN RFC 5389 request (over UDP) and shows the reply information. -.TP -.B +.PP Options with required values: .TP .B @@ -345,9 +348,9 @@ Local address to use (optional). \fB\-f\fP Force RFC 5780 processing. .PP -The \fIturnutils_stunclient\fP program checks the results of the first request, -and if it finds that the STUN server supports RFC 5780 -(the binding response reveals that) then the \fIturnutils_stunclient\fP makes a couple more +The \fIturnutils_stunclient\fP program checks the results of the first request, +and if it finds that the STUN server supports RFC 5780 +(the binding response reveals that) then the \fIturnutils_stunclient\fP makes a couple more requests with different parameters, to demonstrate the NAT discovery capabilities. .PP This utility does not support the "old" "classic" STUN protocol (RFC 3489). @@ -369,12 +372,11 @@ $ \fIturnutils_rfc5769check\fP .fi .SS DESCRIPTION -\fIturnutils_rfc5769check\fP tests the correctness of STUN protocol implementation -against the test vectors predefined in RFC 5769 and prints the results of the +\fIturnutils_rfc5769check\fP tests the correctness of STUN protocol implementation +against the test vectors predefined in RFC 5769 and prints the results of the tests on the screen. This utility is used only for the compilation check procedure, it is not copied to the installation destination. -.TP -.B +.PP Usage: .PP $ \fIturnutils_rfc5769check\fP @@ -397,13 +399,13 @@ $ \fIturnutils_natdiscovery\fP [\fIoptions\fP] Date: Thu, 28 Sep 2017 00:40:40 +0200 Subject: [PATCH 10/17] tidy --- README.turnutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.turnutils b/README.turnutils index 7552b6e..a21fdc9 100644 --- a/README.turnutils +++ b/README.turnutils @@ -463,4 +463,4 @@ SEE ALSO Bradley T. Hughes - Mihaly Meszaros + Mihaly Meszaros From e092f490f8d9c0f956459041508b0e654bf86785 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9sz=C3=A1ros=20Mih=C3=A1ly?= Date: Thu, 28 Sep 2017 13:09:06 +0200 Subject: [PATCH 11/17] hairpinning usage --- src/apps/natdiscovery/natdiscovery.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/natdiscovery/natdiscovery.c b/src/apps/natdiscovery/natdiscovery.c index cd7ae17..ddc1db9 100644 --- a/src/apps/natdiscovery/natdiscovery.c +++ b/src/apps/natdiscovery/natdiscovery.c @@ -520,6 +520,7 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex " -f NAT filtering behavior discovery\n" " -c NAT collision behavior discovery\n" " Requires an alternative IP address (-A)\n" + " -H NAT hairpinning behavior discovery\n" " -P Add 1500 byte Padding to the behavior discovery\n" " Applicable with all except NAT Binding Lifetime discovery\n" " -p STUN server port (Default: 3478)\n" From 9d522822428351ea046a7cdaa5ea0237ab7e8981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9sz=C3=A1ros=20Mih=C3=A1ly?= Date: Thu, 28 Sep 2017 13:23:08 +0200 Subject: [PATCH 12/17] fix init_socket --- src/apps/natdiscovery/natdiscovery.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/apps/natdiscovery/natdiscovery.c b/src/apps/natdiscovery/natdiscovery.c index ddc1db9..e57c01b 100644 --- a/src/apps/natdiscovery/natdiscovery.c +++ b/src/apps/natdiscovery/natdiscovery.c @@ -260,15 +260,7 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780, int change_ip, int change_port, int padding){ int ret=0; - udp_fd = socket(remote_addr->ss.sa_family, SOCK_DGRAM, 0); - if (udp_fd < 0) - err(-1, NULL); - - if (!addr_any(local_addr)) { - if (addr_bind(udp_fd, local_addr,0,1,UDP_SOCKET) < 0) - err(-1, NULL); - } - + ret=init_socket(udp_fd, local_addr, local_port, remote_addr){ ret=stunclient_send(udp_fd, remote_addr, change_ip, change_port, padding, -1); ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, port, rfc5780); close(udp_fd); From 298e9efa419c3af6153d128f4eabebc6f8f8a3c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9sz=C3=A1ros=20Mih=C3=A1ly?= Date: Thu, 28 Sep 2017 18:29:23 +0200 Subject: [PATCH 13/17] hairpinning fixes --- src/apps/natdiscovery/natdiscovery.c | 222 +++++++++++++++++---------- 1 file changed, 138 insertions(+), 84 deletions(-) diff --git a/src/apps/natdiscovery/natdiscovery.c b/src/apps/natdiscovery/natdiscovery.c index e57c01b..e1e8289 100644 --- a/src/apps/natdiscovery/natdiscovery.c +++ b/src/apps/natdiscovery/natdiscovery.c @@ -52,7 +52,27 @@ static int counter = 0; #ifdef __cplusplus -static int stunclient_send(int sockfd, ioa_addr *remote_addr, int change_ip, int change_port, int padding, int response_port){ +static int init_socket(int *socketfd, ioa_addr *local_addr, int local_port, ioa_addr *remote_addr){ + int ret=0; + + if (local_port >= 0) { + addr_set_port(local_addr, local_port); + } + + *socketfd = socket(remote_addr->ss.sa_family, SOCK_DGRAM, 0); + if (udp_fd < 0) + err(-1, NULL); + + if (!addr_any(local_addr)) { + if (addr_bind(*socketfd, local_addr,0,1,UDP_SOCKET) < 0) + err(-1, NULL); + } + + return ret; +} + + +static int stunclient_send(int sockfd, ioa_addr *local_addr, int *local_port, ioa_addr *remote_addr, int change_ip, int change_port, int padding, int response_port){ int ret=0; turn::StunMsgRequest req(STUN_METHOD_BINDING); @@ -122,18 +142,19 @@ static int stunclient_send(int sockfd, ioa_addr *remote_addr, int change_ip, int } + if (addr_get_from_sock(sockfd, local_addr) < 0) { + printf("%s: Cannot get address from local socket\n", __FUNCTION__); + } else { + *local_port = addr_get_port(local_addr); + } + return ret; } -static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780){ +static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *rfc5780){ int ret=0; - if (addr_get_from_sock(sockfd, local_addr) < 0) { - printf("%s: Cannot get address from local socket\n", __FUNCTION__); - } else { - *port = addr_get_port(local_addr); - } { int len = 0; @@ -241,53 +262,37 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex } - static int init_socket(int *socketfd, ioa_addr *local_addr, ioa_addr *remote_addr){ + static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *local_port, int *rfc5780, int change_ip, int change_port, int padding){ int ret=0; - *socketfd = socket(remote_addr->ss.sa_family, SOCK_DGRAM, 0); - if (udp_fd < 0) - err(-1, NULL); - - if (!addr_any(local_addr)) { - if (addr_bind(*socketfd, local_addr,0,1,UDP_SOCKET) < 0) - err(-1, NULL); - } - - return ret; - } - - - static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780, int change_ip, int change_port, int padding){ - int ret=0; - - ret=init_socket(udp_fd, local_addr, local_port, remote_addr){ - ret=stunclient_send(udp_fd, remote_addr, change_ip, change_port, padding, -1); - ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, port, rfc5780); + ret=init_socket(udp_fd, local_addr, *local_port, remote_addr){ + ret=stunclient_send(udp_fd, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); + ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); close(udp_fd); return ret; } - static int run_stunclient_hairpinning(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780, int change_ip, int change_port, int padding){ + static int run_stunclient_hairpinning(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *local_port, int *rfc5780, int change_ip, int change_port, int padding){ int ret=0; - init_socket(&udp_fd,local_addr,remote_addr); + init_socket(&udp_fd,local_addr,*local_port,remote_addr); - ret=stunclient_send(udp_fd, remote_addr, change_ip, change_port, padding, -1); - ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, port, rfc5780); + ret=stunclient_send(udp_fd, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); + ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); addr_cpy(remote_addr,reflexive_addr); addr_set_port(local_addr, 0); - init_socket(&udp_fd2,local_addr,remote_addr); + init_socket(&udp_fd2,local_addr,0,remote_addr); - ret=stunclient_send(udp_fd2, remote_addr, change_ip, change_port, padding, -1); - ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, port, rfc5780); + ret=stunclient_send(udp_fd2, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); + ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); if(ret){ - ret=stunclient_receive(udp_fd2, local_addr, reflexive_addr, other_addr, port, rfc5780); + ret=stunclient_receive(udp_fd2, local_addr, reflexive_addr, other_addr, rfc5780); } close(udp_fd); close(udp_fd2); @@ -297,7 +302,26 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex #else - static int stunclient_send(stun_buffer *buf, int sockfd, ioa_addr *remote_addr, int change_ip, int change_port, int padding, int response_port){ + static int init_socket(int *socketfd, ioa_addr *local_addr, int local_port, ioa_addr *remote_addr){ + int ret=0; + + *socketfd = socket(remote_addr->ss.sa_family, CLIENT_DGRAM_SOCKET_TYPE, CLIENT_DGRAM_SOCKET_PROTOCOL); + if (udp_fd < 0) + err(-1, NULL); + + if (local_port >= 0) { + addr_set_port(local_addr, local_port); + } + if (!addr_any(local_addr)) { + if (addr_bind(*socketfd, local_addr,0,1,UDP_SOCKET) < 0) { + err(-1, NULL); + } + } + + return ret; + } + + static int stunclient_send(stun_buffer *buf, int sockfd, ioa_addr *local_addr, int *local_port, ioa_addr *remote_addr, int change_ip, int change_port, int padding, int response_port){ int ret=0; stun_prepare_binding_request(buf); @@ -327,19 +351,19 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex } + if (addr_get_from_sock(sockfd, local_addr) < 0) { + printf("%s: Cannot get address from local socket\n", __FUNCTION__); + } else { + *local_port = addr_get_port(local_addr); + } + return ret; } - static int stunclient_receive(stun_buffer *buf, int sockfd, ioa_addr *local_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780){ + static int stunclient_receive(stun_buffer *buf, int sockfd, ioa_addr *local_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *rfc5780){ int ret=0; - if (addr_get_from_sock(sockfd, local_addr) < 0) { - printf("%s: Cannot get address from local socket\n", __FUNCTION__); - } else { - *port = addr_get_port(local_addr); - } - { int len = 0; @@ -441,58 +465,41 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex } - static int init_socket(int *socketfd, ioa_addr *local_addr, ioa_addr *remote_addr){ - int ret=0; - - *socketfd = socket(remote_addr->ss.sa_family, CLIENT_DGRAM_SOCKET_TYPE, CLIENT_DGRAM_SOCKET_PROTOCOL); - if (udp_fd < 0) - err(-1, NULL); - - if (!addr_any(local_addr)) { - if (addr_bind(*socketfd, local_addr,0,1,UDP_SOCKET) < 0) { - err(-1, NULL); - } - } - - return ret; - } - - - static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780, int change_ip, int change_port, int padding){ + static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *local_port, int *rfc5780, int change_ip, int change_port, int padding){ int ret=0; stun_buffer buf; - init_socket(&udp_fd,local_addr,remote_addr); + init_socket(&udp_fd, local_addr, *local_port, remote_addr); - ret=stunclient_send(&buf,udp_fd, remote_addr, change_ip, change_port, padding, -1); - ret=stunclient_receive(&buf,udp_fd, local_addr, reflexive_addr, other_addr, port, rfc5780); + ret=stunclient_send(&buf, udp_fd, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); + ret=stunclient_receive(&buf, udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); socket_closesocket(udp_fd); return ret; } - static int run_stunclient_hairpinning(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *port, int *rfc5780, int change_ip, int change_port, int padding){ + static int run_stunclient_hairpinning(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *local_port, int *rfc5780, int change_ip, int change_port, int padding){ int ret=0; stun_buffer buf; stun_buffer buf2; - init_socket(&udp_fd,local_addr,remote_addr); + init_socket(&udp_fd, local_addr, *local_port, remote_addr); - ret=stunclient_send(&buf, udp_fd, remote_addr, change_ip, change_port, padding, -1); - ret=stunclient_receive(&buf, udp_fd, local_addr, reflexive_addr, other_addr, port, rfc5780); + ret=stunclient_send(&buf, udp_fd, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); + ret=stunclient_receive(&buf, udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); addr_cpy(remote_addr,reflexive_addr); addr_set_port(local_addr, 0); - init_socket(&udp_fd2,local_addr,remote_addr); + init_socket(&udp_fd2,local_addr,0,remote_addr); - ret=stunclient_send(&buf2, udp_fd2, remote_addr, change_ip, change_port, padding, -1); - ret=stunclient_receive(&buf, udp_fd, local_addr, reflexive_addr, other_addr, port, rfc5780); + ret=stunclient_send(&buf2, udp_fd2, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); + ret=stunclient_receive(&buf, udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); if(ret){ - ret=stunclient_receive(&buf2, udp_fd2, local_addr, reflexive_addr, other_addr, port, rfc5780); + ret=stunclient_receive(&buf2, udp_fd2, local_addr, reflexive_addr, other_addr, rfc5780); } socket_closesocket(udp_fd); @@ -510,6 +517,8 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex "Options:\n" " -m NAT mapping behavior discovery\n" " -f NAT filtering behavior discovery\n" + " -t NAT binding lifetime behavior discovery\n" + " Requires a timer (-T)\n" " -c NAT collision behavior discovery\n" " Requires an alternative IP address (-A)\n" " -H NAT hairpinning behavior discovery\n" @@ -517,12 +526,15 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex " Applicable with all except NAT Binding Lifetime discovery\n" " -p STUN server port (Default: 3478)\n" " -L Local address to use (optional)\n" + " -l Local port to use (use with -L)\n" " -A Local alrernative address to use\n" - " Used by collision behavior Discovery\n"; + " Used by collision behavior discovery\n" + " -T Binding lifetime timer (sec)\n" + " Used by binding lifetime behavior discovery\n"; ////////////////////////////////////////////////// - static void init(ioa_addr *local_addr,ioa_addr *remote_addr,int *local_port,int port, int *rfc5780, char* local_addr_string, char* remote_param) + static void init(int first, ioa_addr *local_addr, ioa_addr *remote_addr, int *local_port, int port, int *rfc5780, char* local_addr_string, char* remote_param) { addr_set_any(local_addr); @@ -531,8 +543,7 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex err(-1,NULL); } } - - *local_port = -1; + if (!first) *local_port=-1; *rfc5780 = 0; if (make_ioa_addr((const u08bits*)remote_param, port, remote_addr) < 0) @@ -547,16 +558,20 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex int main(int argc, char **argv) { - int port = DEFAULT_STUN_PORT; + int remote_port = DEFAULT_STUN_PORT; char local_addr_string[256]="\0"; char local2_addr_string[256]="\0"; int c=0; int mapping = 0; int filtering = 0; + int lifetime=0; + int timer=0; int collision = 0; int padding = 0; int hairpinning = 0; - int local_port, rfc5780; + int local_port=-1; + int rfc5780; + int first=1; ioa_addr other_addr, reflexive_addr, tmp_addr, remote_addr, local_addr, local2_addr; @@ -570,7 +585,7 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex addr_set_any(&reflexive_addr); addr_set_any(&tmp_addr); - while ((c = getopt(argc, argv, "mfcPHp:L:A:")) != -1) { + while ((c = getopt(argc, argv, "mftcPHp:L:l:A:T:")) != -1) { switch(c) { case 'm': mapping=1; @@ -578,6 +593,9 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex case 'f': filtering=1; break; + case 't': + lifetime=1; + break; case 'c': collision=1; break; @@ -588,14 +606,20 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex padding=1; break; case 'p': - port = atoi(optarg); + remote_port = atoi(optarg); break; case 'L': STRCPY(local_addr_string, optarg); break; + case 'l': + local_port = atoi(optarg); + break; case 'A': STRCPY(local2_addr_string, optarg); break; + case 'T': + timer = atoi(optarg); + break; default: fprintf(stderr,"%s\n", Usage); exit(1); @@ -613,11 +637,36 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex exit(-1); } - init(&local_addr, &remote_addr, &local_port, port, &rfc5780, local_addr_string, argv[optind]); + if(lifetime && timer){ + fprintf(stderr, "Use \"-T\" to add a timer value (in sec).\n"); + fprintf(stderr, "It is mandatory with \"-b\" binding lifetime behavior detection..\n"); + exit(-1); + } + + if(local_port>=0 && local_addr_string !='\0'){ + fprintf(stderr, "To use local port please specify local address \"-L\"!\n"); + fprintf(stderr, "We need to know the address familly to set the port.\n"); + exit(-1); + } + + + if(lifetime) { + init(first, &local_addr, &remote_addr, &local_port, remote_port, &rfc5780, local_addr_string, argv[optind]); + first=0; + // TODO: create new function run_stunclient_hairpinning(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); + } + if(hairpinning) { + init(first, &local_addr, &remote_addr, &local_port, remote_port, &rfc5780, local_addr_string, argv[optind]); + first=0; run_stunclient_hairpinning(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); } + + if(mapping) { + init(first,&local_addr, &remote_addr, &local_port, remote_port, &rfc5780, local_addr_string, argv[optind]); + first=0; + run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); if (addr_eq(&local_addr,&reflexive_addr)){ discoveryresult("No NAT! (Endpoint Independent Mapping)"); @@ -627,7 +676,7 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex addr_cpy(&tmp_addr, &reflexive_addr); addr_cpy(&remote_addr, &other_addr); - addr_set_port(&remote_addr, port); + addr_set_port(&remote_addr, remote_port); run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); @@ -647,9 +696,11 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex } } - init(&local_addr, &remote_addr, &local_port, port, &rfc5780, local_addr_string, argv[optind]); if(filtering) { + init(first,&local_addr, &remote_addr, &local_port, remote_port, &rfc5780, local_addr_string, argv[optind]); + first=0; + run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); if(addr_eq(&local_addr, &reflexive_addr)){ discoveryresult("No NAT! (Endpoint Independent Mapping)"); @@ -673,9 +724,12 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex } } - init(&local_addr, &remote_addr, &local_port, port, &rfc5780, local_addr_string, argv[optind]); + if(collision) { + init(first,&local_addr, &remote_addr, &local_port, remote_port, &rfc5780, local_addr_string, argv[optind]); + first=0; + addr_set_any(&local2_addr); if(local2_addr_string[0]) { From 4b22e6fae6fe16aa583c75a63701766f80f3255d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9sz=C3=A1ros=20Mih=C3=A1ly?= Date: Fri, 29 Sep 2017 05:58:15 +0200 Subject: [PATCH 14/17] Add mapping lifetime discovery --- src/apps/natdiscovery/natdiscovery.c | 102 +++++++++++++++++++++------ 1 file changed, 80 insertions(+), 22 deletions(-) diff --git a/src/apps/natdiscovery/natdiscovery.c b/src/apps/natdiscovery/natdiscovery.c index e1e8289..7cb5103 100644 --- a/src/apps/natdiscovery/natdiscovery.c +++ b/src/apps/natdiscovery/natdiscovery.c @@ -178,6 +178,11 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex } } while (len < 0 && (errno == EINTR)); + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { + printf("STUN receive timeout..\n"); + ret = 1; + return ret; + } if (recvd > 0) len = recvd; buf.len = len; @@ -244,15 +249,12 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex printf("The response is not a reponse message\n"); } } catch(...) { - if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { - printf("STUN receive timeout..\n"); - }else{ - if (isRequest(buf.buf,(size_t)buf.len)) { - printf("Received a request (maybe a successful hairpinning)\n"); - return ret; - } else { - printf("The response is not a well formed STUN message\n"); - } + turn::StunMsgRequest msg(buf.buf, sizeof(buf.buf), (size_t)buf.len, true); + if (msg.isRequest(buf.buf,(size_t)buf.len)) { + printf("Received a request (maybe a successful hairpinning)\n"); + return ret; + } else { + printf("The response is not a well formed STUN message\n"); } ret=1; } @@ -265,7 +267,7 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *local_port, int *rfc5780, int change_ip, int change_port, int padding){ int ret=0; - ret=init_socket(udp_fd, local_addr, *local_port, remote_addr){ + ret=init_socket(&udp_fd, local_addr, *local_port, remote_addr); ret=stunclient_send(udp_fd, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); close(udp_fd); @@ -300,6 +302,30 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex return ret; } + static int run_stunclient_lifetime(int timer,ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *local_port, int *rfc5780, int change_ip, int change_port, int padding){ + int ret=0; + int response_port; + + init_socket(&udp_fd, local_addr, *local_port, remote_addr); + + ret=stunclient_send(udp_fd, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); + ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); + + addr_set_port(local_addr, 0); + sleep(timer); + + init_socket(&udp_fd2,local_addr,0,remote_addr); + response_port=addr_get_port(reflexive_addr); + + ret=stunclient_send(udp_fd2, local_addr, local_port, remote_addr, change_ip, change_port, padding, response_port); + ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); + + socket_closesocket(udp_fd); + socket_closesocket(udp_fd2); + + return ret; + } + #else static int init_socket(int *socketfd, ioa_addr *local_addr, int local_port, ioa_addr *remote_addr){ @@ -508,6 +534,33 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex return ret; } + + static int run_stunclient_lifetime(int timer,ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *local_port, int *rfc5780, int change_ip, int change_port, int padding){ + int ret=0; + stun_buffer buf; + stun_buffer buf2; + int response_port; + + init_socket(&udp_fd, local_addr, *local_port, remote_addr); + + ret=stunclient_send(&buf, udp_fd, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); + ret=stunclient_receive(&buf, udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); + + addr_set_port(local_addr, 0); + sleep(timer); + + init_socket(&udp_fd2,local_addr,0,remote_addr); + response_port=addr_get_port(reflexive_addr); + + ret=stunclient_send(&buf2, udp_fd2, local_addr, local_port, remote_addr, change_ip, change_port, padding, response_port); + ret=stunclient_receive(&buf, udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); + + socket_closesocket(udp_fd); + socket_closesocket(udp_fd2); + + return ret; + } + #endif //////////////// local definitions ///////////////// @@ -517,20 +570,20 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex "Options:\n" " -m NAT mapping behavior discovery\n" " -f NAT filtering behavior discovery\n" - " -t NAT binding lifetime behavior discovery\n" + " -t NAT mapping lifetime behavior discovery\n" " Requires a timer (-T)\n" " -c NAT collision behavior discovery\n" " Requires an alternative IP address (-A)\n" " -H NAT hairpinning behavior discovery\n" " -P Add 1500 byte Padding to the behavior discovery\n" - " Applicable with all except NAT Binding Lifetime discovery\n" + " Applicable with all except NAT mapping Lifetime discovery\n" " -p STUN server port (Default: 3478)\n" " -L Local address to use (optional)\n" " -l Local port to use (use with -L)\n" " -A Local alrernative address to use\n" " Used by collision behavior discovery\n" - " -T Binding lifetime timer (sec)\n" - " Used by binding lifetime behavior discovery\n"; + " -T Mapping lifetime timer (sec)\n" + " Used by mapping lifetime behavior discovery\n"; ////////////////////////////////////////////////// @@ -565,7 +618,7 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex int mapping = 0; int filtering = 0; int lifetime=0; - int timer=0; + int timer=-1; int collision = 0; int padding = 0; int hairpinning = 0; @@ -631,19 +684,19 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex exit(-1); } - if(collision && local2_addr_string == '\0'){ + if(collision && !strcmp(local2_addr_string,"\0")){ fprintf(stderr, "Use \"-A\" to add an Alternative local IP address.\n"); fprintf(stderr, "It is mandatory with \"-c\" collision behavior detection..\n"); exit(-1); } - if(lifetime && timer){ + if(lifetime && timer==-1){ fprintf(stderr, "Use \"-T\" to add a timer value (in sec).\n"); - fprintf(stderr, "It is mandatory with \"-b\" binding lifetime behavior detection..\n"); + fprintf(stderr, "It is mandatory with \"-b\" mapping lifetime behavior detection..\n"); exit(-1); } - if(local_port>=0 && local_addr_string !='\0'){ + if(local_port>=0 && !strcmp(local_addr_string,"\0")){ fprintf(stderr, "To use local port please specify local address \"-L\"!\n"); fprintf(stderr, "We need to know the address familly to set the port.\n"); exit(-1); @@ -651,12 +704,14 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex if(lifetime) { + printf("\n-= Mapping Lifetime Behavior Discovery =-\n"); init(first, &local_addr, &remote_addr, &local_port, remote_port, &rfc5780, local_addr_string, argv[optind]); first=0; - // TODO: create new function run_stunclient_hairpinning(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); + run_stunclient_lifetime(timer, &local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); } if(hairpinning) { + printf("\n-= Hairpinning Behavior Discovery =-\n"); init(first, &local_addr, &remote_addr, &local_port, remote_port, &rfc5780, local_addr_string, argv[optind]); first=0; run_stunclient_hairpinning(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); @@ -664,6 +719,7 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex if(mapping) { + printf("\n-= Mapping Behavior Discovery =-\n"); init(first,&local_addr, &remote_addr, &local_port, remote_port, &rfc5780, local_addr_string, argv[optind]); first=0; @@ -698,6 +754,7 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex if(filtering) { + printf("\n-= Filtering Behavior Discovery =-\n"); init(first,&local_addr, &remote_addr, &local_port, remote_port, &rfc5780, local_addr_string, argv[optind]); first=0; @@ -727,6 +784,7 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex if(collision) { + printf("\n-= Collision Behavior Discovery =-\n"); init(first,&local_addr, &remote_addr, &local_port, remote_port, &rfc5780, local_addr_string, argv[optind]); first=0; @@ -743,8 +801,8 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex run_stunclient(&local2_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); } - if (!filtering && !mapping && !collision && !hairpinning) { - printf("Please use either -f or -c or -m or -H parameter for Filtering or Mapping behavior discovery.\n"); + if (!filtering && !mapping && !collision && !hairpinning && !lifetime) { + printf("Please use either -f or -m or -c or -t or -H parameter for Filtering or Mapping behavior discovery.\n"); } socket_closesocket(udp_fd); socket_closesocket(udp_fd2); From fee54424630c94fdc3f1f598ffe3ec50b942e0d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9sz=C3=A1ros=20Mih=C3=A1ly?= Date: Fri, 29 Sep 2017 09:34:02 +0200 Subject: [PATCH 15/17] Update man and README according natdiscovery changes --- README.turnutils | 15 +++++++++++++-- man/man1/turnutils.1 | 24 ++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/README.turnutils b/README.turnutils index a21fdc9..76f9c8a 100644 --- a/README.turnutils +++ b/README.turnutils @@ -34,8 +34,8 @@ $ ./scripts/secure_relay.sh 5. turnutils_natdiscovery: a utility that provides NAT behavior discovery according RFC5780. This utility discovers the actual NAT Mapping and Filtering -behavior. Be aweare that at least two different listening IP addresses should -be configured to be able to work properly! +behavior, etc. Be aware that on TURN server side two different listening IP +addresses should be configured to be able to work properly! 6. turnutils_oauth: a utility that provides OAuth access_token generation(AEAD encryption), validation and decryption. This utility inputs @@ -272,19 +272,30 @@ Flags: -f NAT filtering behavior discovery +-t NAT mapping lifetime behavior discovery + Requires a timer (-T) + -c NAT collision behavior discovery -H NAT hairpinning behavior discovery +-P Add 1500 byte Padding to the behavior discovery + Applicable with all except NAT mapping Lifetime discovery + Options with required values: -p STUN server port (Default: 3478) -L Local address to use (optional) +-l Local port to use (use with -L) + -A Secondary Local address (optional) Required for collision discovery +-T Mapping lifetime timer (sec) + Used by mapping lifetime behavior discovery + Usage: $ turnutils_natdiscovery -m -f stun.example.com diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index 371397a..fc9c9ec 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -46,8 +46,8 @@ $ ./scripts/secure_relay.sh 5. \fIturnutils_natdiscovery\fP: a utility that provides NAT behavior discovery according RFC5780. This utility discovers the actual NAT Mapping and Filtering -behavior. Be aweare that at least two different listening IP addresses should -be configured to be able to work properly! +behavior, etc. Be aware that on TURN server side two different listening IP +addresses should be configured to be able to work properly! .TP .B 6. @@ -418,12 +418,22 @@ NAT mapping behavior discovery NAT filtering behavior discovery .TP .B +\fB\-t\fP +NAT mapping lifetime behavior discovery +Requires a timer (\fB\-T\fP) +.TP +.B \fB\-c\fP NAT collision behavior discovery .TP .B \fB\-H\fP NAT hairpinning behavior discovery +.TP +.B +\fB\-P\fP +Add 1500 byte Padding to the behavior discovery +Applicable with all except NAT mapping Lifetime discovery .PP Options with required values: .TP @@ -436,9 +446,18 @@ STUN server port (Default: 3478) Local address to use (optional) .TP .B +\fB\-l\fP +Local port to use (use with \fB\-L\fP) +.TP +.B \fB\-A\fP Secondary Local address (optional) Required for collision discovery +.TP +.B +\fB\-T\fP +Mapping lifetime timer (sec) +Used by mapping lifetime behavior discovery .PP Usage: .PP @@ -650,5 +669,6 @@ Mutsutoshi Yoshimoto Federico Pinna .PP Bradley T. Hughes +.RE .PP Mihaly Meszaros From 4595274bf73b9c8698bee711e757e01752430f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9sz=C3=A1ros=20Mih=C3=A1ly?= Date: Fri, 29 Sep 2017 11:46:09 +0200 Subject: [PATCH 16/17] Add git ignore --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1ac4b08 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +Makefile +bin +build +include +lib From 836bc601da396221b18888b138996748eefe0841 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9sz=C3=A1ros=20Mih=C3=A1ly?= Date: Fri, 29 Sep 2017 12:44:47 +0200 Subject: [PATCH 17/17] indent --- src/apps/natdiscovery/natdiscovery.c | 946 +++++++++++++-------------- 1 file changed, 473 insertions(+), 473 deletions(-) diff --git a/src/apps/natdiscovery/natdiscovery.c b/src/apps/natdiscovery/natdiscovery.c index 7cb5103..a8080c2 100644 --- a/src/apps/natdiscovery/natdiscovery.c +++ b/src/apps/natdiscovery/natdiscovery.c @@ -56,7 +56,7 @@ static int init_socket(int *socketfd, ioa_addr *local_addr, int local_port, ioa_ int ret=0; if (local_port >= 0) { - addr_set_port(local_addr, local_port); + addr_set_port(local_addr, local_port); } *socketfd = socket(remote_addr->ss.sa_family, SOCK_DGRAM, 0); @@ -231,8 +231,8 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex } addr_debug_print(1, other_addr, "Other addr: "); } - addr_debug_print(1, reflexive_addr, "UDP reflexive addr"); - addr_debug_print(1, local_addr, "Local addr: "); + addr_debug_print(1, reflexive_addr, "UDP reflexive addr"); + addr_debug_print(1, local_addr, "Local addr: "); } else { printf("Cannot read the response\n"); } @@ -249,563 +249,563 @@ static int stunclient_receive(int sockfd, ioa_addr *local_addr, ioa_addr *reflex printf("The response is not a reponse message\n"); } } catch(...) { - turn::StunMsgRequest msg(buf.buf, sizeof(buf.buf), (size_t)buf.len, true); - if (msg.isRequest(buf.buf,(size_t)buf.len)) { - printf("Received a request (maybe a successful hairpinning)\n"); - return ret; - } else { - printf("The response is not a well formed STUN message\n"); - } - ret=1; + turn::StunMsgRequest msg(buf.buf, sizeof(buf.buf), (size_t)buf.len, true); + if (msg.isRequest(buf.buf,(size_t)buf.len)) { + printf("Received a request (maybe a successful hairpinning)\n"); + return ret; + } else { + printf("The response is not a well formed STUN message\n"); } + ret=1; } - - return ret; } + return ret; +} - static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *local_port, int *rfc5780, int change_ip, int change_port, int padding){ - int ret=0; - ret=init_socket(&udp_fd, local_addr, *local_port, remote_addr); - ret=stunclient_send(udp_fd, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); - ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); - close(udp_fd); +static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *local_port, int *rfc5780, int change_ip, int change_port, int padding){ + int ret=0; - return ret; + ret=init_socket(&udp_fd, local_addr, *local_port, remote_addr); + ret=stunclient_send(udp_fd, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); + ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); + close(udp_fd); + + return ret; +} + + +static int run_stunclient_hairpinning(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *local_port, int *rfc5780, int change_ip, int change_port, int padding){ + int ret=0; + + init_socket(&udp_fd,local_addr,*local_port,remote_addr); + + ret=stunclient_send(udp_fd, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); + ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); + + + addr_cpy(remote_addr,reflexive_addr); + addr_set_port(local_addr, 0); + + init_socket(&udp_fd2,local_addr,0,remote_addr); + + ret=stunclient_send(udp_fd2, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); + ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); + + if(ret){ + ret=stunclient_receive(udp_fd2, local_addr, reflexive_addr, other_addr, rfc5780); } + close(udp_fd); + close(udp_fd2); + return ret; +} - static int run_stunclient_hairpinning(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *local_port, int *rfc5780, int change_ip, int change_port, int padding){ - int ret=0; +static int run_stunclient_lifetime(int timer,ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *local_port, int *rfc5780, int change_ip, int change_port, int padding){ + int ret=0; + int response_port; - init_socket(&udp_fd,local_addr,*local_port,remote_addr); + init_socket(&udp_fd, local_addr, *local_port, remote_addr); - ret=stunclient_send(udp_fd, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); - ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); + ret=stunclient_send(udp_fd, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); + ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); + addr_set_port(local_addr, 0); + sleep(timer); - addr_cpy(remote_addr,reflexive_addr); - addr_set_port(local_addr, 0); + init_socket(&udp_fd2,local_addr,0,remote_addr); + response_port=addr_get_port(reflexive_addr); - init_socket(&udp_fd2,local_addr,0,remote_addr); + ret=stunclient_send(udp_fd2, local_addr, local_port, remote_addr, change_ip, change_port, padding, response_port); + ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); - ret=stunclient_send(udp_fd2, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); - ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); + socket_closesocket(udp_fd); + socket_closesocket(udp_fd2); - if(ret){ - ret=stunclient_receive(udp_fd2, local_addr, reflexive_addr, other_addr, rfc5780); - } - close(udp_fd); - close(udp_fd2); - - return ret; - } - - static int run_stunclient_lifetime(int timer,ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *local_port, int *rfc5780, int change_ip, int change_port, int padding){ - int ret=0; - int response_port; - - init_socket(&udp_fd, local_addr, *local_port, remote_addr); - - ret=stunclient_send(udp_fd, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); - ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); - - addr_set_port(local_addr, 0); - sleep(timer); - - init_socket(&udp_fd2,local_addr,0,remote_addr); - response_port=addr_get_port(reflexive_addr); - - ret=stunclient_send(udp_fd2, local_addr, local_port, remote_addr, change_ip, change_port, padding, response_port); - ret=stunclient_receive(udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); - - socket_closesocket(udp_fd); - socket_closesocket(udp_fd2); - - return ret; - } + return ret; +} #else - static int init_socket(int *socketfd, ioa_addr *local_addr, int local_port, ioa_addr *remote_addr){ - int ret=0; +static int init_socket(int *socketfd, ioa_addr *local_addr, int local_port, ioa_addr *remote_addr){ + int ret=0; - *socketfd = socket(remote_addr->ss.sa_family, CLIENT_DGRAM_SOCKET_TYPE, CLIENT_DGRAM_SOCKET_PROTOCOL); - if (udp_fd < 0) + *socketfd = socket(remote_addr->ss.sa_family, CLIENT_DGRAM_SOCKET_TYPE, CLIENT_DGRAM_SOCKET_PROTOCOL); + if (udp_fd < 0) + err(-1, NULL); + + if (local_port >= 0) { + addr_set_port(local_addr, local_port); + } + if (!addr_any(local_addr)) { + if (addr_bind(*socketfd, local_addr,0,1,UDP_SOCKET) < 0) { err(-1, NULL); - - if (local_port >= 0) { - addr_set_port(local_addr, local_port); } - if (!addr_any(local_addr)) { - if (addr_bind(*socketfd, local_addr,0,1,UDP_SOCKET) < 0) { - err(-1, NULL); - } - } - - return ret; } - static int stunclient_send(stun_buffer *buf, int sockfd, ioa_addr *local_addr, int *local_port, ioa_addr *remote_addr, int change_ip, int change_port, int padding, int response_port){ - int ret=0; + return ret; +} - stun_prepare_binding_request(buf); +static int stunclient_send(stun_buffer *buf, int sockfd, ioa_addr *local_addr, int *local_port, ioa_addr *remote_addr, int change_ip, int change_port, int padding, int response_port){ + int ret=0; - if (response_port >= 0) { - stun_attr_add_response_port_str((u08bits*) (buf->buf), (size_t*) &(buf->len), (u16bits) response_port); + stun_prepare_binding_request(buf); + + if (response_port >= 0) { + stun_attr_add_response_port_str((u08bits*) (buf->buf), (size_t*) &(buf->len), (u16bits) response_port); + } + if (change_ip || change_port) { + stun_attr_add_change_request_str((u08bits*) buf->buf, (size_t*) &(buf->len), change_ip, change_port); + } + if (padding) { + if(stun_attr_add_padding_str((u08bits*) buf->buf, (size_t*) &(buf->len), 1500)<0) { + printf("%s: ERROR: Cannot add padding\n",__FUNCTION__); } - if (change_ip || change_port) { - stun_attr_add_change_request_str((u08bits*) buf->buf, (size_t*) &(buf->len), change_ip, change_port); - } - if (padding) { - if(stun_attr_add_padding_str((u08bits*) buf->buf, (size_t*) &(buf->len), 1500)<0) { - printf("%s: ERROR: Cannot add padding\n",__FUNCTION__); - } - } - - { - int len = 0; - int slen = get_ioa_addr_len(remote_addr); - - do { - len = sendto(sockfd, buf->buf, buf->len, 0, (struct sockaddr*) remote_addr, (socklen_t) slen); - } while (len < 0 && ((errno == EINTR) || (errno == ENOBUFS) || (errno == EAGAIN))); - - if (len < 0) - err(-1, NULL); - - } - - if (addr_get_from_sock(sockfd, local_addr) < 0) { - printf("%s: Cannot get address from local socket\n", __FUNCTION__); - } else { - *local_port = addr_get_port(local_addr); - } - - return ret; } + { + int len = 0; + int slen = get_ioa_addr_len(remote_addr); - static int stunclient_receive(stun_buffer *buf, int sockfd, ioa_addr *local_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *rfc5780){ - int ret=0; + do { + len = sendto(sockfd, buf->buf, buf->len, 0, (struct sockaddr*) remote_addr, (socklen_t) slen); + } while (len < 0 && ((errno == EINTR) || (errno == ENOBUFS) || (errno == EAGAIN))); + + if (len < 0) + err(-1, NULL); + + } + + if (addr_get_from_sock(sockfd, local_addr) < 0) { + printf("%s: Cannot get address from local socket\n", __FUNCTION__); + } else { + *local_port = addr_get_port(local_addr); + } + + return ret; +} - { - int len = 0; - u08bits *ptr = buf->buf; - int recvd = 0; - const int to_recv = sizeof(buf->buf); - struct timeval tv; +static int stunclient_receive(stun_buffer *buf, int sockfd, ioa_addr *local_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *rfc5780){ + int ret=0; - tv.tv_sec = 3; /* 3 Secs Timeout */ - tv.tv_usec = 0; // Not init'ing this can cause strange errors - setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval)); + { + int len = 0; + u08bits *ptr = buf->buf; + int recvd = 0; + const int to_recv = sizeof(buf->buf); + struct timeval tv; - do { - len = recv(sockfd, ptr, to_recv - recvd, 0); - if (len > 0) { - recvd += len; - ptr += len; - break; - } - } while (len < 0 && (errno == EINTR)); + tv.tv_sec = 3; /* 3 Secs Timeout */ + tv.tv_usec = 0; // Not init'ing this can cause strange errors - if (recvd > 0) - len = recvd; - buf->len = len; + setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval)); - if (stun_is_command_message(buf)) { + do { + len = recv(sockfd, ptr, to_recv - recvd, 0); + if (len > 0) { + recvd += len; + ptr += len; + break; + } + } while (len < 0 && (errno == EINTR)); - if (stun_is_response(buf)) { + if (recvd > 0) + len = recvd; + buf->len = len; - if (stun_is_success_response(buf)) { + if (stun_is_command_message(buf)) { - if (stun_is_binding_response(buf)) { + if (stun_is_response(buf)) { - addr_set_any(reflexive_addr); - if (stun_attr_get_first_addr(buf, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, reflexive_addr, NULL) >= 0) { + if (stun_is_success_response(buf)) { - stun_attr_ref sar = stun_attr_get_first_by_type_str(buf->buf, buf->len, STUN_ATTRIBUTE_OTHER_ADDRESS); - if (sar) { - *rfc5780 = 1; - printf("\n========================================\n"); - printf("RFC 5780 response %d\n",++counter); - ioa_addr mapped_addr; - addr_set_any(&mapped_addr); - if (stun_attr_get_first_addr(buf, STUN_ATTRIBUTE_MAPPED_ADDRESS, &mapped_addr, NULL) >= 0) { - if (!addr_eq(&mapped_addr,reflexive_addr)){ - printf("-= ALG detected! Mapped and XOR-Mapped differ! =-\n"); - addr_debug_print(1, &mapped_addr, "Mapped Address: "); - }else { - printf("No ALG: Mapped == XOR-Mapped\n"); - } - } else { - printf("Not received mapped address attribute.\n"); + if (stun_is_binding_response(buf)) { + + addr_set_any(reflexive_addr); + if (stun_attr_get_first_addr(buf, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, reflexive_addr, NULL) >= 0) { + + stun_attr_ref sar = stun_attr_get_first_by_type_str(buf->buf, buf->len, STUN_ATTRIBUTE_OTHER_ADDRESS); + if (sar) { + *rfc5780 = 1; + printf("\n========================================\n"); + printf("RFC 5780 response %d\n",++counter); + ioa_addr mapped_addr; + addr_set_any(&mapped_addr); + if (stun_attr_get_first_addr(buf, STUN_ATTRIBUTE_MAPPED_ADDRESS, &mapped_addr, NULL) >= 0) { + if (!addr_eq(&mapped_addr,reflexive_addr)){ + printf("-= ALG detected! Mapped and XOR-Mapped differ! =-\n"); + addr_debug_print(1, &mapped_addr, "Mapped Address: "); + }else { + printf("No ALG: Mapped == XOR-Mapped\n"); } - stun_attr_get_addr_str((u08bits *) buf->buf, (size_t) buf->len, sar, other_addr, NULL); - sar = stun_attr_get_first_by_type_str(buf->buf, buf->len, STUN_ATTRIBUTE_RESPONSE_ORIGIN); - if (sar) { - ioa_addr response_origin; - stun_attr_get_addr_str((u08bits *) buf->buf, (size_t) buf->len, sar, &response_origin, NULL); - addr_debug_print(1, &response_origin, "Response origin: "); - } - addr_debug_print(1, other_addr, "Other addr: "); + } else { + printf("Not received mapped address attribute.\n"); } - addr_debug_print(1, reflexive_addr, "UDP reflexive addr"); - addr_debug_print(1, local_addr, "Local addr: "); - } else { - printf("Cannot read the response\n"); + stun_attr_get_addr_str((u08bits *) buf->buf, (size_t) buf->len, sar, other_addr, NULL); + sar = stun_attr_get_first_by_type_str(buf->buf, buf->len, STUN_ATTRIBUTE_RESPONSE_ORIGIN); + if (sar) { + ioa_addr response_origin; + stun_attr_get_addr_str((u08bits *) buf->buf, (size_t) buf->len, sar, &response_origin, NULL); + addr_debug_print(1, &response_origin, "Response origin: "); + } + addr_debug_print(1, other_addr, "Other addr: "); } + addr_debug_print(1, reflexive_addr, "UDP reflexive addr"); + addr_debug_print(1, local_addr, "Local addr: "); } else { - printf("Wrong type of response\n"); + printf("Cannot read the response\n"); } } else { - int err_code = 0; - u08bits err_msg[1025] = "\0"; - size_t err_msg_size = sizeof(err_msg); - if (stun_is_error_response(buf, &err_code, err_msg, err_msg_size)) { - printf("The response is an error %d (%s)\n", err_code, (char*) err_msg); - } else { - printf("The response is an unrecognized error\n"); - } + printf("Wrong type of response\n"); } - } else if (stun_is_request(buf)) { - printf("Received a request (maybe a successful hairpinning)\n"); } else { - printf("The response is not a reponse message\n"); - ret=1; + int err_code = 0; + u08bits err_msg[1025] = "\0"; + size_t err_msg_size = sizeof(err_msg); + if (stun_is_error_response(buf, &err_code, err_msg, err_msg_size)) { + printf("The response is an error %d (%s)\n", err_code, (char*) err_msg); + } else { + printf("The response is an unrecognized error\n"); + } } + } else if (stun_is_request(buf)) { + printf("Received a request (maybe a successful hairpinning)\n"); } else { - if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { - printf("STUN receive timeout..\n"); - }else{ - printf("The response is not a STUN message\n"); - } + printf("The response is not a reponse message\n"); ret=1; } + } else { + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { + printf("STUN receive timeout..\n"); + }else{ + printf("The response is not a STUN message\n"); + } + ret=1; } - - return ret; } + return ret; +} - static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *local_port, int *rfc5780, int change_ip, int change_port, int padding){ - int ret=0; - stun_buffer buf; - init_socket(&udp_fd, local_addr, *local_port, remote_addr); +static int run_stunclient(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *local_port, int *rfc5780, int change_ip, int change_port, int padding){ + int ret=0; + stun_buffer buf; - ret=stunclient_send(&buf, udp_fd, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); - ret=stunclient_receive(&buf, udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); + init_socket(&udp_fd, local_addr, *local_port, remote_addr); - socket_closesocket(udp_fd); + ret=stunclient_send(&buf, udp_fd, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); + ret=stunclient_receive(&buf, udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); - return ret; + socket_closesocket(udp_fd); + + return ret; +} + +static int run_stunclient_hairpinning(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *local_port, int *rfc5780, int change_ip, int change_port, int padding){ + int ret=0; + stun_buffer buf; + stun_buffer buf2; + + init_socket(&udp_fd, local_addr, *local_port, remote_addr); + + ret=stunclient_send(&buf, udp_fd, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); + ret=stunclient_receive(&buf, udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); + + + addr_cpy(remote_addr,reflexive_addr); + addr_set_port(local_addr, 0); + + init_socket(&udp_fd2,local_addr,0,remote_addr); + + ret=stunclient_send(&buf2, udp_fd2, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); + ret=stunclient_receive(&buf, udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); + + if(ret){ + ret=stunclient_receive(&buf2, udp_fd2, local_addr, reflexive_addr, other_addr, rfc5780); } - static int run_stunclient_hairpinning(ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *local_port, int *rfc5780, int change_ip, int change_port, int padding){ - int ret=0; - stun_buffer buf; - stun_buffer buf2; + socket_closesocket(udp_fd); + socket_closesocket(udp_fd2); - init_socket(&udp_fd, local_addr, *local_port, remote_addr); - - ret=stunclient_send(&buf, udp_fd, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); - ret=stunclient_receive(&buf, udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); + return ret; +} - addr_cpy(remote_addr,reflexive_addr); - addr_set_port(local_addr, 0); +static int run_stunclient_lifetime(int timer,ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *local_port, int *rfc5780, int change_ip, int change_port, int padding){ + int ret=0; + stun_buffer buf; + stun_buffer buf2; + int response_port; - init_socket(&udp_fd2,local_addr,0,remote_addr); + init_socket(&udp_fd, local_addr, *local_port, remote_addr); - ret=stunclient_send(&buf2, udp_fd2, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); - ret=stunclient_receive(&buf, udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); + ret=stunclient_send(&buf, udp_fd, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); + ret=stunclient_receive(&buf, udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); - if(ret){ - ret=stunclient_receive(&buf2, udp_fd2, local_addr, reflexive_addr, other_addr, rfc5780); - } + addr_set_port(local_addr, 0); + sleep(timer); - socket_closesocket(udp_fd); - socket_closesocket(udp_fd2); + init_socket(&udp_fd2,local_addr,0,remote_addr); + response_port=addr_get_port(reflexive_addr); - return ret; - } + ret=stunclient_send(&buf2, udp_fd2, local_addr, local_port, remote_addr, change_ip, change_port, padding, response_port); + ret=stunclient_receive(&buf, udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); + socket_closesocket(udp_fd); + socket_closesocket(udp_fd2); - static int run_stunclient_lifetime(int timer,ioa_addr *local_addr, ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_addr *other_addr, int *local_port, int *rfc5780, int change_ip, int change_port, int padding){ - int ret=0; - stun_buffer buf; - stun_buffer buf2; - int response_port; - - init_socket(&udp_fd, local_addr, *local_port, remote_addr); - - ret=stunclient_send(&buf, udp_fd, local_addr, local_port, remote_addr, change_ip, change_port, padding, -1); - ret=stunclient_receive(&buf, udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); - - addr_set_port(local_addr, 0); - sleep(timer); - - init_socket(&udp_fd2,local_addr,0,remote_addr); - response_port=addr_get_port(reflexive_addr); - - ret=stunclient_send(&buf2, udp_fd2, local_addr, local_port, remote_addr, change_ip, change_port, padding, response_port); - ret=stunclient_receive(&buf, udp_fd, local_addr, reflexive_addr, other_addr, rfc5780); - - socket_closesocket(udp_fd); - socket_closesocket(udp_fd2); - - return ret; - } + return ret; +} #endif - //////////////// local definitions ///////////////// +//////////////// local definitions ///////////////// - static char Usage[] = - "Usage: natdiscovery [options] address\n" - "Options:\n" - " -m NAT mapping behavior discovery\n" - " -f NAT filtering behavior discovery\n" - " -t NAT mapping lifetime behavior discovery\n" - " Requires a timer (-T)\n" - " -c NAT collision behavior discovery\n" - " Requires an alternative IP address (-A)\n" - " -H NAT hairpinning behavior discovery\n" - " -P Add 1500 byte Padding to the behavior discovery\n" - " Applicable with all except NAT mapping Lifetime discovery\n" - " -p STUN server port (Default: 3478)\n" - " -L Local address to use (optional)\n" - " -l Local port to use (use with -L)\n" - " -A Local alrernative address to use\n" - " Used by collision behavior discovery\n" - " -T Mapping lifetime timer (sec)\n" - " Used by mapping lifetime behavior discovery\n"; +static char Usage[] = +"Usage: natdiscovery [options] address\n" +"Options:\n" +" -m NAT mapping behavior discovery\n" +" -f NAT filtering behavior discovery\n" +" -t NAT mapping lifetime behavior discovery\n" +" Requires a timer (-T)\n" +" -c NAT collision behavior discovery\n" +" Requires an alternative IP address (-A)\n" +" -H NAT hairpinning behavior discovery\n" +" -P Add 1500 byte Padding to the behavior discovery\n" +" Applicable with all except NAT mapping Lifetime discovery\n" +" -p STUN server port (Default: 3478)\n" +" -L Local address to use (optional)\n" +" -l Local port to use (use with -L)\n" +" -A Local alrernative address to use\n" +" Used by collision behavior discovery\n" +" -T Mapping lifetime timer (sec)\n" +" Used by mapping lifetime behavior discovery\n"; - ////////////////////////////////////////////////// +////////////////////////////////////////////////// - static void init(int first, ioa_addr *local_addr, ioa_addr *remote_addr, int *local_port, int port, int *rfc5780, char* local_addr_string, char* remote_param) - { - addr_set_any(local_addr); +static void init(int first, ioa_addr *local_addr, ioa_addr *remote_addr, int *local_port, int port, int *rfc5780, char* local_addr_string, char* remote_param) +{ + addr_set_any(local_addr); - if(local_addr_string[0]) { - if(make_ioa_addr((const u08bits*)local_addr_string, 0, local_addr)<0) { + if(local_addr_string[0]) { + if(make_ioa_addr((const u08bits*)local_addr_string, 0, local_addr)<0) { + err(-1,NULL); + } + } + if (!first) *local_port=-1; + *rfc5780 = 0; + + if (make_ioa_addr((const u08bits*)remote_param, port, remote_addr) < 0) + err(-1, NULL); +} + +static void discoveryresult(const char *decision){ + printf("\n========================================\n"); + printf("%s",decision); + printf("\n========================================\n"); +} + +int main(int argc, char **argv) +{ + int remote_port = DEFAULT_STUN_PORT; + char local_addr_string[256]="\0"; + char local2_addr_string[256]="\0"; + int c=0; + int mapping = 0; + int filtering = 0; + int lifetime=0; + int timer=-1; + int collision = 0; + int padding = 0; + int hairpinning = 0; + int local_port=-1; + int rfc5780; + int first=1; + ioa_addr other_addr, reflexive_addr, tmp_addr, remote_addr, local_addr, local2_addr; + + + set_logfile("stdout"); + set_system_parameters(0); + + ns_bzero(local_addr_string, sizeof(local_addr_string)); + ns_bzero(local2_addr_string, sizeof(local2_addr_string)); + addr_set_any(&remote_addr); + addr_set_any(&other_addr); + addr_set_any(&reflexive_addr); + addr_set_any(&tmp_addr); + + while ((c = getopt(argc, argv, "mftcPHp:L:l:A:T:")) != -1) { + switch(c) { + case 'm': + mapping=1; + break; + case 'f': + filtering=1; + break; + case 't': + lifetime=1; + break; + case 'c': + collision=1; + break; + case 'H': + hairpinning=1; + break; + case 'P': + padding=1; + break; + case 'p': + remote_port = atoi(optarg); + break; + case 'L': + STRCPY(local_addr_string, optarg); + break; + case 'l': + local_port = atoi(optarg); + break; + case 'A': + STRCPY(local2_addr_string, optarg); + break; + case 'T': + timer = atoi(optarg); + break; + default: + fprintf(stderr,"%s\n", Usage); + exit(1); + } + } + + if(optind>=argc) { + fprintf(stderr, "%s\n", Usage); + exit(-1); + } + + if(collision && !strcmp(local2_addr_string,"\0")){ + fprintf(stderr, "Use \"-A\" to add an Alternative local IP address.\n"); + fprintf(stderr, "It is mandatory with \"-c\" collision behavior detection..\n"); + exit(-1); + } + + if(lifetime && timer==-1){ + fprintf(stderr, "Use \"-T\" to add a timer value (in sec).\n"); + fprintf(stderr, "It is mandatory with \"-b\" mapping lifetime behavior detection..\n"); + exit(-1); + } + + if(local_port>=0 && !strcmp(local_addr_string,"\0")){ + fprintf(stderr, "To use local port please specify local address \"-L\"!\n"); + fprintf(stderr, "We need to know the address familly to set the port.\n"); + exit(-1); + } + + + if(lifetime) { + printf("\n-= Mapping Lifetime Behavior Discovery =-\n"); + init(first, &local_addr, &remote_addr, &local_port, remote_port, &rfc5780, local_addr_string, argv[optind]); + first=0; + run_stunclient_lifetime(timer, &local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); + } + + if(hairpinning) { + printf("\n-= Hairpinning Behavior Discovery =-\n"); + init(first, &local_addr, &remote_addr, &local_port, remote_port, &rfc5780, local_addr_string, argv[optind]); + first=0; + run_stunclient_hairpinning(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); + } + + + if(mapping) { + printf("\n-= Mapping Behavior Discovery =-\n"); + init(first,&local_addr, &remote_addr, &local_port, remote_port, &rfc5780, local_addr_string, argv[optind]); + first=0; + + run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); + if (addr_eq(&local_addr,&reflexive_addr)){ + discoveryresult("No NAT! (Endpoint Independent Mapping)"); + } + if(rfc5780) { + if(!addr_any(&other_addr)){ + addr_cpy(&tmp_addr, &reflexive_addr); + + addr_cpy(&remote_addr, &other_addr); + addr_set_port(&remote_addr, remote_port); + + run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); + + if(addr_eq(&tmp_addr,&reflexive_addr)){ + discoveryresult("NAT with Enpoint Independent Mapping!"); + } else { + addr_cpy(&tmp_addr, &reflexive_addr); + addr_cpy(&remote_addr, &other_addr); + run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); + if(addr_eq(&tmp_addr,&reflexive_addr)){ + discoveryresult("NAT with Address Dependent Mapping!"); + } else { + discoveryresult("NAT with Address and Port Dependent Mapping!"); + } + } + } + } + } + + + if(filtering) { + printf("\n-= Filtering Behavior Discovery =-\n"); + init(first,&local_addr, &remote_addr, &local_port, remote_port, &rfc5780, local_addr_string, argv[optind]); + first=0; + + run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); + if(addr_eq(&local_addr, &reflexive_addr)){ + discoveryresult("No NAT! (Endpoint Independent Mapping)"); + } + if(rfc5780) { + if(!addr_any(&other_addr)){ + int res=0; + res=run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,1,1,padding); + if (!res) { + discoveryresult("NAT with Enpoint Independent Filtering!"); + } else { + res=0; + res=run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,1,padding); + if(!res){ + discoveryresult("NAT with Address Dependent Filtering!"); + } else { + discoveryresult("NAT with Address and Port Dependent Filtering!"); + } + } + } + } + } + + + + if(collision) { + printf("\n-= Collision Behavior Discovery =-\n"); + init(first,&local_addr, &remote_addr, &local_port, remote_port, &rfc5780, local_addr_string, argv[optind]); + first=0; + + addr_set_any(&local2_addr); + + if(local2_addr_string[0]) { + if(make_ioa_addr((const u08bits*)local2_addr_string, 0, &local2_addr)<0) { err(-1,NULL); } } - if (!first) *local_port=-1; - *rfc5780 = 0; - if (make_ioa_addr((const u08bits*)remote_param, port, remote_addr) < 0) - err(-1, NULL); + run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); + addr_set_port(&local2_addr,addr_get_port(&local_addr)); + run_stunclient(&local2_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); } - static void discoveryresult(const char *decision){ - printf("\n========================================\n"); - printf("%s",decision); - printf("\n========================================\n"); + if (!filtering && !mapping && !collision && !hairpinning && !lifetime) { + printf("Please use either -f or -m or -c or -t or -H parameter for Filtering or Mapping behavior discovery.\n"); } + socket_closesocket(udp_fd); + socket_closesocket(udp_fd2); - int main(int argc, char **argv) - { - int remote_port = DEFAULT_STUN_PORT; - char local_addr_string[256]="\0"; - char local2_addr_string[256]="\0"; - int c=0; - int mapping = 0; - int filtering = 0; - int lifetime=0; - int timer=-1; - int collision = 0; - int padding = 0; - int hairpinning = 0; - int local_port=-1; - int rfc5780; - int first=1; - ioa_addr other_addr, reflexive_addr, tmp_addr, remote_addr, local_addr, local2_addr; - - - set_logfile("stdout"); - set_system_parameters(0); - - ns_bzero(local_addr_string, sizeof(local_addr_string)); - ns_bzero(local2_addr_string, sizeof(local2_addr_string)); - addr_set_any(&remote_addr); - addr_set_any(&other_addr); - addr_set_any(&reflexive_addr); - addr_set_any(&tmp_addr); - - while ((c = getopt(argc, argv, "mftcPHp:L:l:A:T:")) != -1) { - switch(c) { - case 'm': - mapping=1; - break; - case 'f': - filtering=1; - break; - case 't': - lifetime=1; - break; - case 'c': - collision=1; - break; - case 'H': - hairpinning=1; - break; - case 'P': - padding=1; - break; - case 'p': - remote_port = atoi(optarg); - break; - case 'L': - STRCPY(local_addr_string, optarg); - break; - case 'l': - local_port = atoi(optarg); - break; - case 'A': - STRCPY(local2_addr_string, optarg); - break; - case 'T': - timer = atoi(optarg); - break; - default: - fprintf(stderr,"%s\n", Usage); - exit(1); - } - } - - if(optind>=argc) { - fprintf(stderr, "%s\n", Usage); - exit(-1); - } - - if(collision && !strcmp(local2_addr_string,"\0")){ - fprintf(stderr, "Use \"-A\" to add an Alternative local IP address.\n"); - fprintf(stderr, "It is mandatory with \"-c\" collision behavior detection..\n"); - exit(-1); - } - - if(lifetime && timer==-1){ - fprintf(stderr, "Use \"-T\" to add a timer value (in sec).\n"); - fprintf(stderr, "It is mandatory with \"-b\" mapping lifetime behavior detection..\n"); - exit(-1); - } - - if(local_port>=0 && !strcmp(local_addr_string,"\0")){ - fprintf(stderr, "To use local port please specify local address \"-L\"!\n"); - fprintf(stderr, "We need to know the address familly to set the port.\n"); - exit(-1); - } - - - if(lifetime) { - printf("\n-= Mapping Lifetime Behavior Discovery =-\n"); - init(first, &local_addr, &remote_addr, &local_port, remote_port, &rfc5780, local_addr_string, argv[optind]); - first=0; - run_stunclient_lifetime(timer, &local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); - } - - if(hairpinning) { - printf("\n-= Hairpinning Behavior Discovery =-\n"); - init(first, &local_addr, &remote_addr, &local_port, remote_port, &rfc5780, local_addr_string, argv[optind]); - first=0; - run_stunclient_hairpinning(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); - } - - - if(mapping) { - printf("\n-= Mapping Behavior Discovery =-\n"); - init(first,&local_addr, &remote_addr, &local_port, remote_port, &rfc5780, local_addr_string, argv[optind]); - first=0; - - run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); - if (addr_eq(&local_addr,&reflexive_addr)){ - discoveryresult("No NAT! (Endpoint Independent Mapping)"); - } - if(rfc5780) { - if(!addr_any(&other_addr)){ - addr_cpy(&tmp_addr, &reflexive_addr); - - addr_cpy(&remote_addr, &other_addr); - addr_set_port(&remote_addr, remote_port); - - run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); - - if(addr_eq(&tmp_addr,&reflexive_addr)){ - discoveryresult("NAT with Enpoint Independent Mapping!"); - } else { - addr_cpy(&tmp_addr, &reflexive_addr); - addr_cpy(&remote_addr, &other_addr); - run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); - if(addr_eq(&tmp_addr,&reflexive_addr)){ - discoveryresult("NAT with Address Dependent Mapping!"); - } else { - discoveryresult("NAT with Address and Port Dependent Mapping!"); - } - } - } - } - } - - - if(filtering) { - printf("\n-= Filtering Behavior Discovery =-\n"); - init(first,&local_addr, &remote_addr, &local_port, remote_port, &rfc5780, local_addr_string, argv[optind]); - first=0; - - run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); - if(addr_eq(&local_addr, &reflexive_addr)){ - discoveryresult("No NAT! (Endpoint Independent Mapping)"); - } - if(rfc5780) { - if(!addr_any(&other_addr)){ - int res=0; - res=run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,1,1,padding); - if (!res) { - discoveryresult("NAT with Enpoint Independent Filtering!"); - } else { - res=0; - res=run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,1,padding); - if(!res){ - discoveryresult("NAT with Address Dependent Filtering!"); - } else { - discoveryresult("NAT with Address and Port Dependent Filtering!"); - } - } - } - } - } - - - - if(collision) { - printf("\n-= Collision Behavior Discovery =-\n"); - init(first,&local_addr, &remote_addr, &local_port, remote_port, &rfc5780, local_addr_string, argv[optind]); - first=0; - - addr_set_any(&local2_addr); - - if(local2_addr_string[0]) { - if(make_ioa_addr((const u08bits*)local2_addr_string, 0, &local2_addr)<0) { - err(-1,NULL); - } - } - - run_stunclient(&local_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); - addr_set_port(&local2_addr,addr_get_port(&local_addr)); - run_stunclient(&local2_addr, &remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,0,0,padding); - } - - if (!filtering && !mapping && !collision && !hairpinning && !lifetime) { - printf("Please use either -f or -m or -c or -t or -H parameter for Filtering or Mapping behavior discovery.\n"); - } - socket_closesocket(udp_fd); - socket_closesocket(udp_fd2); - - return 0; - } + return 0; +}