diff options
author | Christian Grothoff <christian@grothoff.org> | 2010-02-08 12:52:43 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2010-02-08 12:52:43 +0000 |
commit | 19b13a33872cef3616e188daade61fc8b662ea35 (patch) | |
tree | e8ece8d018912d126d3af3297a7956bee8146b8a /src | |
parent | 0cc9e15f6613fa10058b429de0350e5632d38695 (diff) | |
download | gnunet-19b13a33872cef3616e188daade61fc8b662ea35.tar.gz gnunet-19b13a33872cef3616e188daade61fc8b662ea35.zip |
more
Diffstat (limited to 'src')
-rwxr-xr-x | src/transport/gnunet-nat-client-script.sh | 4 | ||||
-rw-r--r-- | src/transport/gnunet-nat-client-udp.c | 298 | ||||
-rwxr-xr-x | src/transport/gnunet-nat-server-script.sh | 4 | ||||
-rw-r--r-- | src/transport/gnunet-nat-server-udp.c | 278 |
4 files changed, 584 insertions, 0 deletions
diff --git a/src/transport/gnunet-nat-client-script.sh b/src/transport/gnunet-nat-client-script.sh new file mode 100755 index 000000000..4e4ccafad --- /dev/null +++ b/src/transport/gnunet-nat-client-script.sh | |||
@@ -0,0 +1,4 @@ | |||
1 | #!/bin/sh | ||
2 | IP=`ifconfig | grep inet | head -n1 | awk '{print $2}' | sed -e "s/addr://"` | ||
3 | echo "Using IP $IP, trying to connect to $1" | ||
4 | ./gnunet-nat-client-udp $IP $1 | ||
diff --git a/src/transport/gnunet-nat-client-udp.c b/src/transport/gnunet-nat-client-udp.c new file mode 100644 index 000000000..c17710b61 --- /dev/null +++ b/src/transport/gnunet-nat-client-udp.c | |||
@@ -0,0 +1,298 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2010 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file src/transport/client-test.c | ||
23 | * @brief Test for NAT traversal using ICMP method. | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include <sys/types.h> | ||
27 | #include <sys/socket.h> | ||
28 | #include <arpa/inet.h> | ||
29 | #include <sys/types.h> | ||
30 | #include <unistd.h> | ||
31 | #include <stdio.h> | ||
32 | #include <string.h> | ||
33 | #include <errno.h> | ||
34 | #include <stdlib.h> | ||
35 | #include <stdint.h> | ||
36 | #include <netinet/in.h> | ||
37 | #include <time.h> | ||
38 | |||
39 | /** | ||
40 | * How often do we send our UDP messages to keep ports open (and to | ||
41 | * try to connect, of course). Use small value since we are the | ||
42 | * initiator and should hence be rather aggressive. | ||
43 | */ | ||
44 | #define UDP_SEND_FREQUENCY_MS 5 | ||
45 | |||
46 | /** | ||
47 | * Port we always try to use. | ||
48 | */ | ||
49 | #define NAT_TRAV_PORT 22223 | ||
50 | |||
51 | /** | ||
52 | * Number of UDP ports to keep open at the same time (typically >= 256). | ||
53 | * Should be less than FD_SETSIZE. | ||
54 | */ | ||
55 | #define NUM_UDP_PORTS 1000 | ||
56 | |||
57 | /** | ||
58 | * How often do we retry to open and bind a UDP socket before giving up? | ||
59 | */ | ||
60 | #define MAX_BIND_TRIES 10 | ||
61 | |||
62 | /** | ||
63 | * How often do we try at most? We expect to need (for the worst kind | ||
64 | * of NAT) on average 64512 / 512 = 126 attempts to have the right | ||
65 | * destination port and we then need to also (in the worst case) have | ||
66 | * the right source port (so 126 * 64512 = 8128512 packets on | ||
67 | * average!). That's obviously a bit much, so we give up earlier. The | ||
68 | * given value corresponds to about 1 minute of runtime (for a send | ||
69 | * frequency of one packet per ms). | ||
70 | * | ||
71 | * NOW: if the *server* would listen for Linux-generated ICMP | ||
72 | * "Destination unreachables" we *might* increase our chances since | ||
73 | * maybe the firewall has some older/other UDP rules (this was | ||
74 | * the case during testing for me), but obviously that would mean | ||
75 | * more SUID'ed code. Yuck. | ||
76 | */ | ||
77 | #define MAX_TRIES 62500 | ||
78 | |||
79 | #define LOW_PORT 32768 | ||
80 | |||
81 | /** | ||
82 | * create a random port number that is not totally | ||
83 | * unlikely to be chosen by the nat box. | ||
84 | */ | ||
85 | static uint16_t | ||
86 | make_port () | ||
87 | { | ||
88 | return LOW_PORT + ( (unsigned int)rand ()) % (64 * 1024 - LOW_PORT); | ||
89 | } | ||
90 | |||
91 | |||
92 | /** | ||
93 | * create a fresh udp socket bound to a random local port, | ||
94 | * or, if the argument is zero, to the NAT_TRAV_PORT. | ||
95 | * | ||
96 | * @param i counter | ||
97 | * @return -1 on error | ||
98 | */ | ||
99 | static int | ||
100 | make_udp_socket (int i) | ||
101 | { | ||
102 | int ret; | ||
103 | int tries; | ||
104 | struct sockaddr_in src; | ||
105 | |||
106 | for (tries=0;tries<MAX_BIND_TRIES;tries++) | ||
107 | { | ||
108 | ret = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); | ||
109 | if (-1 == ret) | ||
110 | { | ||
111 | fprintf (stderr, | ||
112 | "Error opening udp socket: %s\n", | ||
113 | strerror (errno)); | ||
114 | return -1; | ||
115 | } | ||
116 | if (ret >= FD_SETSIZE) | ||
117 | { | ||
118 | fprintf (stderr, | ||
119 | "Socket number too large (%d > %u)\n", | ||
120 | ret, | ||
121 | (unsigned int) FD_SETSIZE); | ||
122 | close (ret); | ||
123 | return -1; | ||
124 | } | ||
125 | memset (&src, 0, sizeof (src)); | ||
126 | src.sin_family = AF_INET; | ||
127 | if (i == 0) | ||
128 | src.sin_port = htons (NAT_TRAV_PORT); | ||
129 | else | ||
130 | src.sin_port = htons (make_port ()); | ||
131 | if (0 != bind (ret, (struct sockaddr*) &src, sizeof (src))) | ||
132 | { | ||
133 | close (ret); | ||
134 | continue; | ||
135 | } | ||
136 | return ret; | ||
137 | } | ||
138 | fprintf (stderr, | ||
139 | "Error binding udp socket: %s\n", | ||
140 | strerror (errno)); | ||
141 | return -1; | ||
142 | } | ||
143 | |||
144 | |||
145 | |||
146 | |||
147 | int | ||
148 | main (int argc, char *const *argv) | ||
149 | { | ||
150 | int udpsocks[NUM_UDP_PORTS]; | ||
151 | char command[512]; | ||
152 | struct in_addr external; | ||
153 | struct in_addr target; | ||
154 | int ret; | ||
155 | unsigned int pos; | ||
156 | int i; | ||
157 | int max; | ||
158 | struct sockaddr_in dst; | ||
159 | struct sockaddr_in src; | ||
160 | int first_round = 1; | ||
161 | char dummybuf[65536]; | ||
162 | unsigned int tries; | ||
163 | struct timeval tv; | ||
164 | socklen_t slen; | ||
165 | fd_set rs; | ||
166 | |||
167 | if (argc != 3) | ||
168 | { | ||
169 | fprintf (stderr, | ||
170 | "This program must be started with our IP and the targets external IP as arguments.\n"); | ||
171 | return 1; | ||
172 | } | ||
173 | if ( (1 != inet_pton (AF_INET, argv[1], &external)) || | ||
174 | (1 != inet_pton (AF_INET, argv[2], &target)) ) | ||
175 | { | ||
176 | fprintf (stderr, | ||
177 | "Error parsing IPv4 address: %s\n", | ||
178 | strerror (errno)); | ||
179 | return 1; | ||
180 | } | ||
181 | snprintf (command, | ||
182 | sizeof (command), | ||
183 | "gnunet-nat-client %s %s", | ||
184 | argv[1], | ||
185 | argv[2]); | ||
186 | if (0 != (ret = system (command))) | ||
187 | { | ||
188 | if (ret == -1) | ||
189 | fprintf (stderr, | ||
190 | "Error running `%s': %s\n", | ||
191 | command, | ||
192 | strerror (errno)); | ||
193 | return 1; | ||
194 | } | ||
195 | fprintf (stderr, | ||
196 | "Trying to connect to `%s'\n", | ||
197 | argv[2]); | ||
198 | srand (time(NULL)); | ||
199 | for (i=0;i<NUM_UDP_PORTS;i++) | ||
200 | udpsocks[i] = make_udp_socket (i); | ||
201 | memset (&dst, 0, sizeof (dst)); | ||
202 | dst.sin_family = AF_INET; | ||
203 | dst.sin_addr = target; | ||
204 | pos = 0; | ||
205 | tries = 0; | ||
206 | while (MAX_TRIES > tries++) | ||
207 | { | ||
208 | FD_ZERO (&rs); | ||
209 | for (i=0;i<NUM_UDP_PORTS;i++) | ||
210 | { | ||
211 | if (udpsocks[i] != -1) | ||
212 | FD_SET (udpsocks[i], &rs); | ||
213 | if (udpsocks[i] > max) | ||
214 | max = udpsocks[i]; | ||
215 | } | ||
216 | tv.tv_sec = 0; | ||
217 | tv.tv_usec = UDP_SEND_FREQUENCY_MS * 1000; | ||
218 | select (max + 1, &rs, NULL, NULL, &tv); | ||
219 | for (i=0;i<NUM_UDP_PORTS;i++) | ||
220 | { | ||
221 | if (udpsocks[i] == -1) | ||
222 | continue; | ||
223 | if (! FD_ISSET (udpsocks[i], &rs)) | ||
224 | continue; | ||
225 | slen = sizeof (src); | ||
226 | recvfrom (udpsocks[i], | ||
227 | dummybuf, sizeof (dummybuf), 0, | ||
228 | (struct sockaddr*) &src, | ||
229 | &slen); | ||
230 | if (slen != sizeof (src)) | ||
231 | { | ||
232 | fprintf (stderr, | ||
233 | "Unexpected size of address.\n"); | ||
234 | continue; | ||
235 | } | ||
236 | if (0 != memcmp (&src.sin_addr, | ||
237 | &target, | ||
238 | sizeof (external))) | ||
239 | { | ||
240 | fprintf (stderr, | ||
241 | "Unexpected sender IP\n"); | ||
242 | continue; | ||
243 | } | ||
244 | /* discovered port! */ | ||
245 | fprintf (stdout, | ||
246 | "%s:%u\n", | ||
247 | argv[2], | ||
248 | ntohs (src.sin_port)); | ||
249 | dst.sin_port = src.sin_port; | ||
250 | if (-1 == sendto (udpsocks[i], | ||
251 | NULL, 0, 0, | ||
252 | (struct sockaddr*) &dst, sizeof (dst))) | ||
253 | { | ||
254 | fprintf (stderr, | ||
255 | "sendto failed: %s\n", | ||
256 | strerror (errno)); | ||
257 | return 2; /* oops */ | ||
258 | } | ||
259 | /* success! */ | ||
260 | fprintf (stderr, | ||
261 | "Succeeded after %u packets.\n", | ||
262 | tries); | ||
263 | return 0; | ||
264 | } | ||
265 | if (udpsocks[pos] == -1) | ||
266 | { | ||
267 | udpsocks[pos] = make_udp_socket (pos); | ||
268 | continue; | ||
269 | } | ||
270 | if ( (0 == ((unsigned int)rand() % NUM_UDP_PORTS)) || | ||
271 | (1 == first_round) ) | ||
272 | dst.sin_port = htons (NAT_TRAV_PORT); | ||
273 | else | ||
274 | dst.sin_port = htons (make_port ()); | ||
275 | fprintf (stderr, | ||
276 | "Sending UDP packet to `%s:%u'\n", | ||
277 | argv[2], | ||
278 | ntohs (dst.sin_port)); | ||
279 | first_round = 0; | ||
280 | if (-1 == sendto (udpsocks[pos], | ||
281 | NULL, 0, 0, | ||
282 | (struct sockaddr*) &dst, sizeof (dst))) | ||
283 | { | ||
284 | fprintf (stderr, | ||
285 | "sendto failed: %s\n", | ||
286 | strerror (errno)); | ||
287 | close (udpsocks[pos]); | ||
288 | udpsocks[pos] = make_udp_socket (pos); | ||
289 | } | ||
290 | pos = (pos+1) % NUM_UDP_PORTS; | ||
291 | } | ||
292 | fprintf (stderr, | ||
293 | "Giving up after %u tries.\n", | ||
294 | tries); | ||
295 | return 3; | ||
296 | } | ||
297 | |||
298 | /* end of client-test.c */ | ||
diff --git a/src/transport/gnunet-nat-server-script.sh b/src/transport/gnunet-nat-server-script.sh new file mode 100755 index 000000000..42a8e639a --- /dev/null +++ b/src/transport/gnunet-nat-server-script.sh | |||
@@ -0,0 +1,4 @@ | |||
1 | #!/bin/sh | ||
2 | IP=`ifconfig | grep inet | head -n1 | awk '{print $2}' | sed -e "s/addr://"` | ||
3 | echo "Using IP $IP" | ||
4 | ./gnunet-nat-server $IP | sed -u -e "s/.*/.\/gnunet-nat-server-udp $IP &\&/" | sh | ||
diff --git a/src/transport/gnunet-nat-server-udp.c b/src/transport/gnunet-nat-server-udp.c new file mode 100644 index 000000000..693adbcf5 --- /dev/null +++ b/src/transport/gnunet-nat-server-udp.c | |||
@@ -0,0 +1,278 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2010 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file src/transport/server-test.c | ||
23 | * @brief Test for NAT traversal using ICMP method. | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include <sys/types.h> | ||
27 | #include <sys/socket.h> | ||
28 | #include <arpa/inet.h> | ||
29 | #include <sys/types.h> | ||
30 | #include <unistd.h> | ||
31 | #include <stdio.h> | ||
32 | #include <string.h> | ||
33 | #include <errno.h> | ||
34 | #include <stdlib.h> | ||
35 | #include <stdint.h> | ||
36 | #include <netinet/in.h> | ||
37 | #include <time.h> | ||
38 | |||
39 | |||
40 | |||
41 | /** | ||
42 | * How often do we send our UDP messages to keep ports open (and to | ||
43 | * try to connect, of course). Assuming the NAT closes UDP ports | ||
44 | * after 60s, we need at least about 100ms here for 512 ports; | ||
45 | * however, we should open the ports quickly (and we don't yet | ||
46 | * differentiate between the first round and later rounds), so we pick | ||
47 | * a much lower value here for now. | ||
48 | */ | ||
49 | #define UDP_SEND_FREQUENCY_MS 50 | ||
50 | |||
51 | /** | ||
52 | * Port we always try to use. | ||
53 | */ | ||
54 | #define NAT_TRAV_PORT 22225 | ||
55 | |||
56 | /** | ||
57 | * Number of UDP ports to keep open at the same time (typically >= 256). | ||
58 | * Should be less than FD_SETSIZE. | ||
59 | */ | ||
60 | #define NUM_UDP_PORTS 1000 | ||
61 | |||
62 | /** | ||
63 | * How often do we retry to open and bind a UDP socket before giving up? | ||
64 | */ | ||
65 | #define MAX_BIND_TRIES 10 | ||
66 | |||
67 | /** | ||
68 | * How long do we try at most? We expect the other side to give | ||
69 | * up after about one minute for now. | ||
70 | */ | ||
71 | #define MAX_DURATION 60000 | ||
72 | |||
73 | #define LOW_PORT 32768 | ||
74 | |||
75 | /** | ||
76 | * create a random port number that is not totally | ||
77 | * unlikely to be chosen by the nat box. | ||
78 | */ | ||
79 | static uint16_t | ||
80 | make_port () | ||
81 | { | ||
82 | return LOW_PORT + ( (unsigned int)rand ()) % (64 * 1024 - LOW_PORT - 2); | ||
83 | } | ||
84 | |||
85 | |||
86 | /** | ||
87 | * create a fresh udp socket bound to a random local port, | ||
88 | * or, if the argument is zero, to the NAT_TRAV_PORT. | ||
89 | * | ||
90 | * @param i counter | ||
91 | * @return -1 on error | ||
92 | */ | ||
93 | static int | ||
94 | make_udp_socket (int i) | ||
95 | { | ||
96 | int ret; | ||
97 | int tries; | ||
98 | struct sockaddr_in src; | ||
99 | |||
100 | for (tries=0;tries<MAX_BIND_TRIES;tries++) | ||
101 | { | ||
102 | ret = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); | ||
103 | if (-1 == ret) | ||
104 | { | ||
105 | fprintf (stderr, | ||
106 | "Error opening udp socket: %s\n", | ||
107 | strerror (errno)); | ||
108 | return -1; | ||
109 | } | ||
110 | if (ret >= FD_SETSIZE) | ||
111 | { | ||
112 | fprintf (stderr, | ||
113 | "Socket number too large (%d > %u)\n", | ||
114 | ret, | ||
115 | (unsigned int) FD_SETSIZE); | ||
116 | close (ret); | ||
117 | return -1; | ||
118 | } | ||
119 | memset (&src, 0, sizeof (src)); | ||
120 | src.sin_family = AF_INET; | ||
121 | if (i == 0) | ||
122 | src.sin_port = htons (NAT_TRAV_PORT); | ||
123 | else | ||
124 | src.sin_port = htons (make_port ()); | ||
125 | if (0 != bind (ret, (struct sockaddr*) &src, sizeof (src))) | ||
126 | { | ||
127 | close (ret); | ||
128 | continue; | ||
129 | } | ||
130 | return ret; | ||
131 | } | ||
132 | fprintf (stderr, | ||
133 | "Error binding udp socket: %s\n", | ||
134 | strerror (errno)); | ||
135 | return -1; | ||
136 | } | ||
137 | |||
138 | |||
139 | int | ||
140 | main (int argc, char *const *argv) | ||
141 | { | ||
142 | int udpsocks[NUM_UDP_PORTS]; | ||
143 | char command[512]; | ||
144 | struct in_addr external; | ||
145 | struct in_addr target; | ||
146 | int ret; | ||
147 | unsigned int pos; | ||
148 | int i; | ||
149 | int max; | ||
150 | struct sockaddr_in dst; | ||
151 | struct sockaddr_in src; | ||
152 | int first_round = 1; | ||
153 | char dummybuf[65536]; | ||
154 | unsigned int tries; | ||
155 | struct timeval tv; | ||
156 | socklen_t slen; | ||
157 | fd_set rs; | ||
158 | time_t stime; | ||
159 | |||
160 | if (argc != 3) | ||
161 | { | ||
162 | fprintf (stderr, | ||
163 | "This program must be started with our IP and the targets external IP as arguments.\n"); | ||
164 | return 1; | ||
165 | } | ||
166 | if ( (1 != inet_pton (AF_INET, argv[1], &external)) || | ||
167 | (1 != inet_pton (AF_INET, argv[2], &target)) ) | ||
168 | { | ||
169 | fprintf (stderr, | ||
170 | "Error parsing IPv4 address: %s\n", | ||
171 | strerror (errno)); | ||
172 | return 1; | ||
173 | } | ||
174 | fprintf (stderr, | ||
175 | "Trying to connect to %s\n", | ||
176 | argv[2]); | ||
177 | srand (stime = time(NULL)); | ||
178 | for (i=0;i<NUM_UDP_PORTS;i++) | ||
179 | udpsocks[i] = make_udp_socket (i); | ||
180 | memset (&dst, 0, sizeof (dst)); | ||
181 | dst.sin_family = AF_INET; | ||
182 | dst.sin_addr = target; | ||
183 | pos = 0; | ||
184 | tries = 0; | ||
185 | while (stime + MAX_DURATION >= time (NULL)) | ||
186 | { | ||
187 | tries++; | ||
188 | FD_ZERO (&rs); | ||
189 | for (i=0;i<NUM_UDP_PORTS;i++) | ||
190 | { | ||
191 | if (udpsocks[i] != -1) | ||
192 | FD_SET (udpsocks[i], &rs); | ||
193 | if (udpsocks[i] > max) | ||
194 | max = udpsocks[i]; | ||
195 | } | ||
196 | tv.tv_sec = 0; | ||
197 | tv.tv_usec = UDP_SEND_FREQUENCY_MS * 1000; | ||
198 | select (max + 1, &rs, NULL, NULL, &tv); | ||
199 | for (i=0;i<NUM_UDP_PORTS;i++) | ||
200 | { | ||
201 | if (udpsocks[i] == -1) | ||
202 | continue; | ||
203 | if (! FD_ISSET (udpsocks[i], &rs)) | ||
204 | continue; | ||
205 | slen = sizeof (src); | ||
206 | recvfrom (udpsocks[i], | ||
207 | dummybuf, sizeof (dummybuf), 0, | ||
208 | (struct sockaddr*) &src, | ||
209 | &slen); | ||
210 | if (slen != sizeof (src)) | ||
211 | { | ||
212 | fprintf (stderr, | ||
213 | "Unexpected size of address.\n"); | ||
214 | continue; | ||
215 | } | ||
216 | if (0 != memcmp (&src.sin_addr, | ||
217 | &target, | ||
218 | sizeof (external))) | ||
219 | { | ||
220 | fprintf (stderr, | ||
221 | "Unexpected sender IP\n"); | ||
222 | continue; | ||
223 | } | ||
224 | /* discovered port! */ | ||
225 | fprintf (stdout, | ||
226 | "%s:%u\n", | ||
227 | argv[2], | ||
228 | ntohs (src.sin_port)); | ||
229 | dst.sin_port = src.sin_port; | ||
230 | if (-1 == sendto (udpsocks[i], | ||
231 | NULL, 0, 0, | ||
232 | (struct sockaddr*) &dst, sizeof (dst))) | ||
233 | { | ||
234 | fprintf (stderr, | ||
235 | "sendto failed: %s\n", | ||
236 | strerror (errno)); | ||
237 | return 2; /* oops */ | ||
238 | } | ||
239 | /* success! */ | ||
240 | fprintf (stderr, | ||
241 | "Succeeded after %u packets.\n", | ||
242 | tries); | ||
243 | return 0; | ||
244 | } | ||
245 | if (udpsocks[pos] == -1) | ||
246 | { | ||
247 | udpsocks[pos] = make_udp_socket (pos); | ||
248 | continue; | ||
249 | } | ||
250 | if ( (0 == ((unsigned int)rand() % NUM_UDP_PORTS)) || | ||
251 | (1 == first_round) ) | ||
252 | dst.sin_port = htons (NAT_TRAV_PORT); | ||
253 | else | ||
254 | dst.sin_port = htons (make_port ()); | ||
255 | fprintf (stderr, | ||
256 | "Sending UDP packet to `%s:%u'\n", | ||
257 | argv[2], | ||
258 | ntohs (dst.sin_port)); | ||
259 | first_round = 0; | ||
260 | if (-1 == sendto (udpsocks[pos], | ||
261 | NULL, 0, 0, | ||
262 | (struct sockaddr*) &dst, sizeof (dst))) | ||
263 | { | ||
264 | fprintf (stderr, | ||
265 | "sendto failed: %s\n", | ||
266 | strerror (errno)); | ||
267 | close (udpsocks[pos]); | ||
268 | udpsocks[pos] = make_udp_socket (pos); | ||
269 | } | ||
270 | pos = (pos+1) % NUM_UDP_PORTS; | ||
271 | } | ||
272 | fprintf (stderr, | ||
273 | "Giving up after %u tries.\n", | ||
274 | tries); | ||
275 | return 3; | ||
276 | } | ||
277 | |||
278 | /* end of server-test.c */ | ||