aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-07-01 14:17:34 +0000
committerChristian Grothoff <christian@grothoff.org>2011-07-01 14:17:34 +0000
commit6129a0a79b56923d483216ba78ba250c2cf0403c (patch)
treebb379ed2d3035497cf939e28a21ab70985a3dd0a
parent0e4eb80cafbc54240c5d82589dea973d6ee22df3 (diff)
downloadgnunet-6129a0a79b56923d483216ba78ba250c2cf0403c.tar.gz
gnunet-6129a0a79b56923d483216ba78ba250c2cf0403c.zip
more hacking on nat test code
-rw-r--r--src/include/gnunet_nat_lib.h2
-rw-r--r--src/nat/nat.c27
-rw-r--r--src/nat/nat_test.c296
3 files changed, 310 insertions, 15 deletions
diff --git a/src/include/gnunet_nat_lib.h b/src/include/gnunet_nat_lib.h
index 07f6ca5e8..1eb8b5703 100644
--- a/src/include/gnunet_nat_lib.h
+++ b/src/include/gnunet_nat_lib.h
@@ -162,7 +162,7 @@ typedef void (*GNUNET_NAT_TestCallback)(void *cls,
162 * 162 *
163 * @param cfg configuration for the NAT traversal 163 * @param cfg configuration for the NAT traversal
164 * @param is_tcp GNUNET_YES to test TCP, GNUNET_NO to test UDP 164 * @param is_tcp GNUNET_YES to test TCP, GNUNET_NO to test UDP
165 * @param bnd_port port to bind to 165 * @param bnd_port port to bind to, 0 for connection reversal
166 * @param adv_port externally advertised port to use 166 * @param adv_port externally advertised port to use
167 * @param report function to call with the result of the test 167 * @param report function to call with the result of the test
168 * @param report_cls closure for report 168 * @param report_cls closure for report
diff --git a/src/nat/nat.c b/src/nat/nat.c
index e708cdabf..4e78c5d24 100644
--- a/src/nat/nat.c
+++ b/src/nat/nat.c
@@ -331,10 +331,11 @@ remove_from_address_list_by_source (struct GNUNET_NAT_Handle *h,
331 GNUNET_CONTAINER_DLL_remove (h->lal_head, 331 GNUNET_CONTAINER_DLL_remove (h->lal_head,
332 h->lal_tail, 332 h->lal_tail,
333 pos); 333 pos);
334 h->address_callback (h->callback_cls, 334 if (NULL != h->address_callback)
335 GNUNET_NO, 335 h->address_callback (h->callback_cls,
336 (const struct sockaddr* ) &pos[1], 336 GNUNET_NO,
337 pos->addrlen); 337 (const struct sockaddr* ) &pos[1],
338 pos->addrlen);
338 GNUNET_free (pos); 339 GNUNET_free (pos);
339 } 340 }
340} 341}
@@ -369,10 +370,11 @@ add_to_address_list_as_is (struct GNUNET_NAT_Handle *h,
369 "Adding address `%s' from source %d\n", 370 "Adding address `%s' from source %d\n",
370 GNUNET_a2s (arg, arg_size), 371 GNUNET_a2s (arg, arg_size),
371 src); 372 src);
372 h->address_callback (h->callback_cls, 373 if (NULL != h->address_callback)
373 GNUNET_YES, 374 h->address_callback (h->callback_cls,
374 arg, 375 GNUNET_YES,
375 arg_size); 376 arg,
377 arg_size);
376} 378}
377 379
378 380
@@ -1273,10 +1275,11 @@ GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *h)
1273 GNUNET_CONTAINER_DLL_remove (h->lal_head, 1275 GNUNET_CONTAINER_DLL_remove (h->lal_head,
1274 h->lal_tail, 1276 h->lal_tail,
1275 lal); 1277 lal);
1276 h->address_callback (h->callback_cls, 1278 if (NULL != h->address_callback)
1277 GNUNET_NO, 1279 h->address_callback (h->callback_cls,
1278 (const struct sockaddr*) &lal[1], 1280 GNUNET_NO,
1279 lal->addrlen); 1281 (const struct sockaddr*) &lal[1],
1282 lal->addrlen);
1280 GNUNET_free (lal); 1283 GNUNET_free (lal);
1281 } 1284 }
1282 for (i=0;i<h->num_local_addrs;i++) 1285 for (i=0;i<h->num_local_addrs;i++)
diff --git a/src/nat/nat_test.c b/src/nat/nat_test.c
index f31c5059d..a8bf227a0 100644
--- a/src/nat/nat_test.c
+++ b/src/nat/nat_test.c
@@ -28,25 +28,249 @@
28#include "gnunet_nat_lib.h" 28#include "gnunet_nat_lib.h"
29#include "nat.h" 29#include "nat.h"
30 30
31/**
32 *
33 */
34struct NatActivity
35{
36 /**
37 *
38 */
39 struct NatActivity *next;
40
41 /**
42 *
43 */
44 struct NatActivity *prev;
45
46 /**
47 *
48 */
49 struct GNUNET_NETWORK_Handle *sock;
50
51 /**
52 *
53 */
54 struct GNUNET_NAT_Test *h;
55
56 /**
57 *
58 */
59 GNUNET_SCHEDULER_TaskIdentifier rtask;
60};
31 61
32/** 62/**
33 * Handle to a NAT test. 63 * Handle to a NAT test.
34 */ 64 */
35struct GNUNET_NAT_Test 65struct GNUNET_NAT_Test
36{ 66{
67
68 /**
69 *
70 */
71 const struct GNUNET_CONFIGURATION_Handle *cfg;
72
73 /**
74 *
75 */
37 GNUNET_NAT_TestCallback report; 76 GNUNET_NAT_TestCallback report;
38 77
78 /**
79 *
80 */
39 void *report_cls; 81 void *report_cls;
82
83 /**
84 *
85 */
86 struct GNUNET_NAT_Handle *nat;
87
88 /**
89 *
90 */
91 struct GNUNET_NETWORK_Handle *lsock;
92
93 /**
94 *
95 */
96 struct NatActivity *head;
97
98 /**
99 *
100 */
101 struct NatActivity *tail;
102
103 /**
104 *
105 */
106 GNUNET_SCHEDULER_TaskIdentifier ltask;
107
108 /**
109 *
110 */
111 int is_tcp;
112
113 /**
114 *
115 */
116 uint16_t data;
117
118 /**
119 *
120 */
121 uint16_t adv_port;
122
40}; 123};
41 124
42 125
43/** 126/**
127 * Function called from GNUNET_NAT_register
128 * whenever someone asks us to do connection
129 * reversal.
130 *
131 * @param cls closure, our 'struct GNUNET_NAT_Handle'
132 * @param addr public IP address of the other peer
133 * @param addrlen actual lenght of the address
134 */
135static void
136reversal_cb (void *cls,
137 const struct sockaddr *addr,
138 socklen_t addrlen)
139{
140 struct GNUNET_NAT_Test *h = cls;
141 const struct sockaddr_in *sa;
142
143 if (addrlen != sizeof (struct sockaddr_in))
144 return;
145 sa = (const struct sockaddr_in *) addr;
146 if (h->data != sa->sin_port)
147 {
148 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
149 "Received connection reversal request for wrong port\n");
150 return; /* wrong port */
151 }
152 /* report success */
153 h->report (h->report_cls, GNUNET_OK);
154}
155
156
157/**
158 * Activity on our incoming socket. Read data from the
159 * incoming connection.
160 *
161 * @param cls the 'struct NatActivity'
162 * @param tc scheduler context
163 */
164static void
165do_read (void *cls,
166 const struct GNUNET_SCHEDULER_TaskContext *tc)
167{
168 struct NatActivity *na = cls;
169 struct GNUNET_NAT_Test *tst;
170
171 na->rtask = GNUNET_SCHEDULER_NO_TASK;
172 tst = na->h;
173 GNUNET_CONTAINER_DLL_remove (tst->head,
174 tst->tail,
175 na);
176 if (1)
177 {
178 // fimxe: read from socket...
179 }
180 GNUNET_NETWORK_socket_close (na->sock);
181 GNUNET_free (na);
182}
183
184
185/**
186 * Activity on our listen socket. Accept the
187 * incoming connection.
188 *
189 * @param cls the 'struct GNUNET_NAT_Test'
190 * @param tc scheduler context
191 */
192static void
193do_accept (void *cls,
194 const struct GNUNET_SCHEDULER_TaskContext *tc)
195{
196 struct GNUNET_NAT_Test *tst = cls;
197 struct GNUNET_NETWORK_Handle *s;
198 struct NatActivity *wl;
199
200 tst->ltask = GNUNET_SCHEDULER_NO_TASK;
201 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
202 return;
203 tst->ltask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
204 tst->lsock,
205 &do_accept,
206 tst);
207 s = GNUNET_NETWORK_socket_accept (tst->lsock, NULL, NULL);
208 if (NULL == s)
209 return; /* odd error */
210 wl = GNUNET_malloc (sizeof (struct NatActivity));
211 wl->sock = s;
212 wl->h = tst;
213 wl->rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
214 wl->sock,
215 &do_read,
216 wl);
217 GNUNET_CONTAINER_DLL_insert (tst->head,
218 tst->tail,
219 wl);
220}
221
222
223/**
224 * Address-callback, used to send message to gnunet-nat-server.
225 *
226 * @param cls closure
227 * @param add_remove GNUNET_YES to mean the new public IP address, GNUNET_NO to mean
228 * the previous (now invalid) one
229 * @param addr either the previous or the new public IP address
230 * @param addrlen actual lenght of the address
231 */
232static void
233addr_cb (void *cls,
234 int add_remove,
235 const struct sockaddr *addr,
236 socklen_t addrlen)
237{
238 struct GNUNET_NAT_Test *h = cls;
239 struct GNUNET_CLIENT_Connection *client;
240 struct GNUNET_NAT_TestMessage msg;
241 const struct sockaddr_in *sa;
242
243 if (GNUNET_YES != add_remove)
244 return;
245 if (addrlen != sizeof (struct sockaddr_in))
246 return; /* ignore IPv6 here */
247 sa = (const struct sockaddr_in*) addr;
248 msg.header.size = htons (sizeof(struct GNUNET_NAT_TestMessage));
249 msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAT_TEST);
250 msg.dst_ipv4 = sa->sin_addr.s_addr;
251 msg.dport = sa->sin_port;
252 msg.data = h->data;
253 msg.is_tcp = htonl ((uint32_t) h->is_tcp);
254
255 client = GNUNET_CLIENT_connect ("gnunet-nat-server",
256 h->cfg);
257 GNUNET_break (GNUNET_OK ==
258 GNUNET_CLIENT_transmit_and_get_response (client,
259 &msg.header,
260 GNUNET_TIME_UNIT_SECONDS,
261 GNUNET_YES,
262 NULL, NULL));
263 GNUNET_CLIENT_disconnect (client, GNUNET_YES);
264}
265
266
267/**
44 * Start testing if NAT traversal works using the 268 * Start testing if NAT traversal works using the
45 * given configuration (IPv4-only). 269 * given configuration (IPv4-only).
46 * 270 *
47 * @param cfg configuration for the NAT traversal 271 * @param cfg configuration for the NAT traversal
48 * @param is_tcp GNUNET_YES to test TCP, GNUNET_NO to test UDP 272 * @param is_tcp GNUNET_YES to test TCP, GNUNET_NO to test UDP
49 * @param bnd_port port to bind to 273 * @param bnd_port port to bind to, 0 for connection reversal
50 * @param adv_port externally advertised port to use 274 * @param adv_port externally advertised port to use
51 * @param report function to call with the result of the test 275 * @param report function to call with the result of the test
52 * @param report_cls closure for report 276 * @param report_cls closure for report
@@ -60,7 +284,59 @@ GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
60 GNUNET_NAT_TestCallback report, 284 GNUNET_NAT_TestCallback report,
61 void *report_cls) 285 void *report_cls)
62{ 286{
63 return NULL; 287 struct GNUNET_NAT_Test *ret;
288 struct sockaddr_in sa;
289 const struct sockaddr *addrs[] = { (const struct sockaddr*) &sa };
290 const socklen_t addrlens[] = { sizeof (sa) };
291
292 memset (&sa, 0, sizeof (sa));
293 sa.sin_port = htons (bnd_port);
294#if HAVE_SOCKADDR_IN_SIN_LEN
295 sa.sin_len = sizeof (sa);
296#endif
297
298 ret = GNUNET_malloc (sizeof (struct GNUNET_NAT_Test));
299 ret->cfg = cfg;
300 ret->is_tcp = is_tcp;
301 ret->data = bnd_port;
302 ret->adv_port = adv_port;
303 ret->report = report;
304 ret->report_cls = report_cls;
305 if (bnd_port == 0)
306 {
307 ret->nat = GNUNET_NAT_register (cfg, is_tcp,
308 0,
309 0, NULL, NULL,
310 &addr_cb, &reversal_cb, ret);
311 }
312 else
313 {
314 ret->lsock = GNUNET_NETWORK_socket_create (AF_INET,
315 (is_tcp==GNUNET_YES) ? SOCK_STREAM : SOCK_DGRAM, 0);
316 if ( (ret->lsock == NULL) ||
317 (GNUNET_OK != GNUNET_NETWORK_socket_bind (ret->lsock,
318 (const struct sockaddr*) &sa,
319 sizeof (sa))) )
320 {
321 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
322 _("Failed to create listen socket for NAT test\n"));
323 if (NULL != ret->lsock)
324 GNUNET_NETWORK_socket_close (ret->lsock);
325 GNUNET_free (ret);
326 return NULL;
327 }
328 GNUNET_break (GNUNET_OK ==
329 GNUNET_NETWORK_socket_listen (ret->lsock, 5));
330 ret->ltask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
331 ret->lsock,
332 &do_accept,
333 ret);
334 ret->nat = GNUNET_NAT_register (cfg, is_tcp,
335 adv_port,
336 1, addrs, addrlens,
337 &addr_cb, NULL, ret);
338 }
339 return ret;
64} 340}
65 341
66 342
@@ -72,6 +348,22 @@ GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
72void 348void
73GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst) 349GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst)
74{ 350{
351 struct NatActivity *pos;
352
353 while (NULL != (pos = tst->head))
354 {
355 GNUNET_CONTAINER_DLL_remove (tst->head,
356 tst->tail,
357 pos);
358 GNUNET_SCHEDULER_cancel (pos->rtask);
359 GNUNET_NETWORK_socket_close (pos->sock);
360 GNUNET_free (pos);
361 }
362 if (GNUNET_SCHEDULER_NO_TASK != tst->ltask)
363 GNUNET_SCHEDULER_cancel (tst->ltask);
364 if (NULL != tst->lsock)
365 GNUNET_NETWORK_socket_close (tst->lsock);
366 GNUNET_NAT_unregister (tst->nat);
75 GNUNET_free (tst); 367 GNUNET_free (tst);
76} 368}
77 369