1 /* 2 * nat_test.cpp 3 * NAT type testing. 4 * 5 * Created by Gertjan Halkes. 6 * Copyright 2010 Delft University of Technology. All rights reserved. 7 * 8 */ 9 10 #include "swift.h" 11 #ifdef _WIN32 12 #include <iphlpapi.h> 13 #else 14 #include <sys/types.h> 15 #include <sys/socket.h> 16 #include <ifaddrs.h> 17 #include <errno.h> 18 #include <netinet/in.h> 19 #endif 20 21 #define REQUEST_MAGIC 0x5a9e5fa1 22 #define REPLY_MAGIC 0xa655c5d5 23 #define REPLY_SEC_MAGIC 0x85e4a5ca 24 #define MAX_TRIES 3 25 namespace swift 26 { 27 28 static void on_may_receive(SOCKET sock); 29 static void on_may_send(SOCKET sock); 30 static tint test_start; 31 static int tries; 32 static int packets_since_last_try; 33 34 static sckrwecb_t callbacks(0, on_may_receive, on_may_send, NULL); 35 /* Note that we lookup the addresses when we actually send, because Windows requires that 36 the winsock library is first intialized. If we use Address type variables here, the 37 lookup would be tried before that initialization, which fails... */ 38 //FIXME: Change addresses to actual addresses used in test (at least 2 should be provided!) 39 static const char *servers[] = { "dutigp.st.ewi.tudelft.nl:18375" , 40 "127.0.0.3:18375" 41 }; 42 43 static void on_may_receive(SOCKET sock) 44 { 45 Datagram data(sock); 46 47 data.Recv(); 48 49 uint32_t magic = data.Pull32(); 50 if ((magic != REPLY_MAGIC && magic != REPLY_SEC_MAGIC) || 51 (magic == REPLY_MAGIC && data.size() != 6) || (magic == REPLY_SEC_MAGIC && data.size() != 0)) { 52 dprintf("%s #0 NATTEST weird packet %s \n", tintstr(), data.address().str().c_str()); 53 return; 54 } 55 56 if (magic == REPLY_MAGIC) { 57 uint32_t ip = data.Pull32(); 58 uint16_t port = data.Pull16(); 59 Address reported(ip, port); 60 dprintf("%s #0 NATTEST incoming %s %s\n", tintstr(), data.address().str().c_str(), reported.str().c_str()); 61 } else { 62 dprintf("%s #0 NATTEST incoming secondary %s\n", tintstr(), data.address().str().c_str()); 63 } 64 packets_since_last_try++; 65 } 66 67 static void on_may_send(SOCKET sock) 68 { 69 callbacks.may_write = NULL; 70 Datagram::Listen3rdPartySocket(callbacks); 71 72 for (size_t i = 0; i < (sizeof(servers)/sizeof(servers[0])); i++) { 73 Datagram request(sock, Address(servers[i])); 74 75 request.Push32(REQUEST_MAGIC); 76 request.Send(); 77 } 78 test_start = NOW; 79 80 struct sockaddr_in name; 81 socklen_t namelen = sizeof(name); 82 if (getsockname(sock, (struct sockaddr *) &name, &namelen) < 0) { 83 dprintf("%s #0 NATTEST could not get local address\n", tintstr()); 84 } else { 85 Address local(ntohl(name.sin_addr.s_addr), ntohs(name.sin_port)); 86 dprintf("%s #0 NATTEST local %s\n", tintstr(), local.str().c_str()); 87 } 88 } 89 90 static void printAddresses(void) 91 { 92 #ifdef _WIN32 93 IP_ADAPTER_INFO *adapterInfo = NULL; 94 IP_ADAPTER_INFO *adapter = NULL; 95 DWORD retval = 0; 96 UINT i; 97 ULONG size = 0; 98 99 if ((retval = GetAdaptersInfo(adapterInfo, &size)) != ERROR_BUFFER_OVERFLOW) { 100 dprintf("ERROR: %d\n", (int) retval); 101 return; 102 } 103 104 adapterInfo = (IP_ADAPTER_INFO *) malloc(size); 105 if (adapterInfo == NULL) { 106 dprintf("ERROR: out of memory\n"); 107 return; 108 } 109 110 if ((retval = GetAdaptersInfo(adapterInfo, &size)) == NO_ERROR) { 111 adapter = adapterInfo; 112 while (adapter) { 113 IP_ADDR_STRING *address; 114 for (address = &adapter->IpAddressList; address != NULL; address = address->Next) { 115 if (address->IpAddress.String[0] != 0) 116 dprintf("ADDRESS: %s\n", address->IpAddress.String); 117 } 118 adapter = adapter->Next; 119 } 120 } else { 121 dprintf("ERROR: %d\n", (int) retval); 122 } 123 free(adapterInfo); 124 #else 125 struct ifaddrs *addrs, *ptr; 126 if (getifaddrs(&addrs) < 0) { 127 dprintf("ERROR: %s\n", strerror(errno)); 128 return; 129 } 130 131 for (ptr = addrs; ptr != NULL; ptr = ptr->ifa_next) { 132 if (ptr->ifa_addr->sa_family == AF_INET) { 133 dprintf("ADDRESS: %s\n", inet_ntoa(((struct sockaddr_in *) ptr->ifa_addr)->sin_addr)); 134 } 135 } 136 freeifaddrs(addrs); 137 #endif 138 } 139 140 141 } 142