From ed33482a49a70f82b017358844731ae00fb3c59f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9sz=C3=A1ros=20Mih=C3=A1ly?= Date: Mon, 11 Apr 2016 12:42:08 +0000 Subject: [PATCH] functionality extended with NAT filtering detection, according rfc5780 --- src/apps/natdiscovery/natdiscovery.c | 170 +++++++++++++++++++-------- 1 file changed, 119 insertions(+), 51 deletions(-) diff --git a/src/apps/natdiscovery/natdiscovery.c b/src/apps/natdiscovery/natdiscovery.c index 10b675e..ad50cc7 100644 --- a/src/apps/natdiscovery/natdiscovery.c +++ b/src/apps/natdiscovery/natdiscovery.c @@ -53,7 +53,7 @@ static int counter = 0; 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) { - + int ret=0; if (response_port >= 0) { addr_set_port(&real_local_addr, response_port); @@ -149,6 +149,12 @@ static int run_stunclient(ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_a 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 + + setsockopt(udp_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval)); do { len = recv(udp_fd, ptr, to_recv - recvd, 0); @@ -213,18 +219,19 @@ static int run_stunclient(ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_a } } catch(...) { printf("The response is not a well formed STUN message\n"); + ret=1; } } close(udp_fd); - return 0; + return ret; } #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) { - + int ret=0; stun_buffer buf; udp_fd = socket(remote_addr->ss.sa_family, CLIENT_DGRAM_SOCKET_TYPE, CLIENT_DGRAM_SOCKET_PROTOCOL); @@ -280,6 +287,12 @@ static int run_stunclient(ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_a 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 + + setsockopt(udp_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval)); do { len = recv(udp_fd, ptr, to_recv - recvd, 0); @@ -288,7 +301,14 @@ static int run_stunclient(ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_a ptr += len; break; } - } while (len < 0 && ((errno == EINTR) || (errno == EAGAIN))); + if (errno == EINTR) + printf("EINTR"); + if (errno == EAGAIN) + printf("EAGAIN"); + if (errno == EWOULDBLOCK) + printf("EWOULDBLOCK"); + + } while (len < 0 && (errno == EINTR)); if (recvd > 0) len = recvd; @@ -339,34 +359,62 @@ static int run_stunclient(ioa_addr *remote_addr, ioa_addr *reflexive_addr, ioa_a } } else { printf("The response is not a reponse message\n"); + ret=1; } } else { printf("The response is not a STUN message\n"); + ret=1; } } socket_closesocket(udp_fd); - return 0; + return ret; } #endif //////////////// local definitions ///////////////// static char Usage[] = - "Usage: stunclient [options] address\n" + "Usage: natdiscovery [options] address\n" "Options:\n" + " -m NAT mapping behavior discovery\n" + " -f NAT filtering behavior discovery\n" " -p STUN server port (Default: 3478)\n" - " -L Local address to use (optional)\n" - " -f Force RFC 5780 processing\n"; + " -L Local address to use (optional)\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) +{ + addr_set_any(real_local_addr); + + if(local_addr[0]) { + if(make_ioa_addr((const u08bits*)local_addr, 0, real_local_addr)<0) { + err(-1,NULL); + } + } + + *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 port = DEFAULT_STUN_PORT; char local_addr[256]="\0"; int c=0; - int forceRfc5780 = 0; + int mapping = 0; + int filtering = 0; + int local_port, rfc5780; ioa_addr other_addr, reflexive_addr, tmp_addr, remote_addr; @@ -379,12 +427,14 @@ int main(int argc, char **argv) addr_set_any(&reflexive_addr); addr_set_any(&tmp_addr); - - while ((c = getopt(argc, argv, "p:L:f")) != -1) { + while ((c = getopt(argc, argv, "mfp:L:")) != -1) { switch(c) { + case 'm': + mapping=1; + break; case 'f': - forceRfc5780 = 1; - break; + filtering=1; + break; case 'p': port = atoi(optarg); break; @@ -402,50 +452,68 @@ int main(int argc, char **argv) exit(-1); } - addr_set_any(&real_local_addr); + init(&real_local_addr, &remote_addr, &local_port, port, &rfc5780, local_addr, argv[optind]); - if(local_addr[0]) { - if(make_ioa_addr((const u08bits*)local_addr, 0, &real_local_addr)<0) { - err(-1,NULL); - } + 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)){ + 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(&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); + if(addr_eq(&tmp_addr,&reflexive_addr)){ + discoveryresult("NAT with Address Dependent Mapping!"); + } else { + discoveryresult("NAT with Address and Port Dependent Mapping!"); + } + }; + + } + } } + + init(&real_local_addr, &remote_addr, &local_port, port, &rfc5780, local_addr, argv[optind]); - int local_port = -1; - int rfc5780 = 0; + 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)){ + 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); + 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); + if(!res){ + discoveryresult("NAT with Address Dependent Filtering!"); + } else { + discoveryresult("NAT with Address and Port Dependent Filtering!"); + } + }; - if (make_ioa_addr((const u08bits*)argv[optind], port, &remote_addr) < 0) - err(-1, NULL); - - - run_stunclient(&remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,0); - if (addr_eq(&real_local_addr,&reflexive_addr)){ - printf("No NAT! (Endpoint Independent Mapping)"); + } + } } - if(rfc5780 || forceRfc5780) { - 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(&remote_addr, &reflexive_addr, &other_addr, &local_port, &rfc5780,-1,0,0,0); - - if(addr_eq(&tmp_addr,&reflexive_addr)){ - printf("NAT with Enpoint Independent Mapping!\n"); - } 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); - if(addr_eq(&tmp_addr,&reflexive_addr)){ - printf("NAT with Address Dependent Mapping!\n"); - } else { - printf("NAT with Address and Port Dependent Mapping!\n"); - } - }; - } + if (!filtering && !mapping) { + printf("Please use either -f or -m parameter for Filtering or Mapping behavior discovery."); } - socket_closesocket(udp_fd); return 0;