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