diff options
author | Nathan S. Evans <evans@in.tum.de> | 2010-02-19 13:33:17 +0000 |
---|---|---|
committer | Nathan S. Evans <evans@in.tum.de> | 2010-02-19 13:33:17 +0000 |
commit | e1fe5a5ca9711cb615e4c85daf002364592814b9 (patch) | |
tree | 7aee3d55a6c64bbe2171bb2eebd001e057606ee6 /src | |
parent | 6a1a0c383228cff1b85480e4094c66b92a1be9ce (diff) | |
download | gnunet-e1fe5a5ca9711cb615e4c85daf002364592814b9.tar.gz gnunet-e1fe5a5ca9711cb615e4c85daf002364592814b9.zip |
semi functional nat punchy dealy
Diffstat (limited to 'src')
-rw-r--r-- | src/transport/plugin_transport_udp_nat.c | 1627 | ||||
-rw-r--r-- | src/transport/test_transport_api.c | 68 | ||||
-rw-r--r-- | src/transport/test_transport_api_udp_nat_peer1.conf | 137 | ||||
-rw-r--r-- | src/transport/test_transport_api_udp_nat_peer2.conf | 137 |
4 files changed, 1926 insertions, 43 deletions
diff --git a/src/transport/plugin_transport_udp_nat.c b/src/transport/plugin_transport_udp_nat.c new file mode 100644 index 000000000..afa731a38 --- /dev/null +++ b/src/transport/plugin_transport_udp_nat.c | |||
@@ -0,0 +1,1627 @@ | |||
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 2, 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 transport/plugin_transport_udp.c | ||
23 | * @brief Implementation of the UDP NAT punching | ||
24 | * transport service | ||
25 | * @author Christian Grothoff | ||
26 | * @author Nathan Evans | ||
27 | * | ||
28 | * The idea with this transport is to connect gnunet peers to each other | ||
29 | * when one or both is behind a NAT. This is based on pwnat | ||
30 | * (http://samy.pl/pwnat) created by Samy Kamkar. This transport will | ||
31 | * take external IP addresses for a NAT'd peer, start a server daemon | ||
32 | * which sends ICMP messages out to a predefined address. Then it forks | ||
33 | * a client process which sends ICMP death messages to the given external | ||
34 | * IP address for the other peer (which has already also started the | ||
35 | * server). If everything works according to plan, the transport will | ||
36 | * be given a port which has worked to punch into the other external | ||
37 | * addresses NAT to communicate with the other gnunet peer. Then keep | ||
38 | * alive messages will be sent every (???)ms or so to keep the tunnel | ||
39 | * safe. | ||
40 | */ | ||
41 | |||
42 | #include "platform.h" | ||
43 | #include "gnunet_hello_lib.h" | ||
44 | #include "gnunet_connection_lib.h" | ||
45 | #include "gnunet_os_lib.h" | ||
46 | #include "gnunet_peerinfo_service.h" | ||
47 | #include "gnunet_protocols.h" | ||
48 | #include "gnunet_resolver_service.h" | ||
49 | #include "gnunet_server_lib.h" | ||
50 | #include "gnunet_service_lib.h" | ||
51 | #include "gnunet_signatures.h" | ||
52 | #include "gnunet_statistics_service.h" | ||
53 | #include "gnunet_transport_service.h" | ||
54 | #include "plugin_transport.h" | ||
55 | #include "transport.h" | ||
56 | |||
57 | #define DEBUG_UDP_NAT GNUNET_YES | ||
58 | |||
59 | /* | ||
60 | * Transport cost to peer, always 1 for UDP (direct connection) | ||
61 | */ | ||
62 | #define UDP_DIRECT_DISTANCE 1 | ||
63 | |||
64 | /** | ||
65 | * Handle for request of hostname resolution, non-NULL if pending. | ||
66 | */ | ||
67 | static struct GNUNET_RESOLVER_RequestHandle *hostname_dns; | ||
68 | |||
69 | /** | ||
70 | * How long until we give up on transmitting the welcome message? | ||
71 | */ | ||
72 | #define HOSTNAME_RESOLVE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) | ||
73 | |||
74 | /* | ||
75 | * How many ports do we want to listen on (and send on) in order to get replies? | ||
76 | * | ||
77 | * FIXME: make this value dynamic, specified by configuration | ||
78 | */ | ||
79 | #define UDP_NAT_LISTEN_PORTS 1 | ||
80 | |||
81 | /* | ||
82 | * Starting port for listening and sending, eventually a config value | ||
83 | */ | ||
84 | #define UDP_NAT_STARTING_PORT 24857 | ||
85 | |||
86 | /** | ||
87 | * UDP Message-Packet header. | ||
88 | */ | ||
89 | struct UDPMessage | ||
90 | { | ||
91 | /** | ||
92 | * Message header. | ||
93 | */ | ||
94 | struct GNUNET_MessageHeader header; | ||
95 | |||
96 | /** | ||
97 | * What is the identity of the sender (GNUNET_hash of public key) | ||
98 | */ | ||
99 | struct GNUNET_PeerIdentity sender; | ||
100 | |||
101 | }; | ||
102 | |||
103 | |||
104 | /** | ||
105 | * UDP NAT Probe message definition | ||
106 | */ | ||
107 | struct UDP_NAT_ProbeMessage | ||
108 | { | ||
109 | /** | ||
110 | * Message header | ||
111 | */ | ||
112 | struct GNUNET_MessageHeader header; | ||
113 | |||
114 | }; | ||
115 | |||
116 | /** | ||
117 | * UDP NAT Probe message reply definition | ||
118 | */ | ||
119 | struct UDP_NAT_ProbeMessageReply | ||
120 | { | ||
121 | /** | ||
122 | * Message header | ||
123 | */ | ||
124 | struct GNUNET_MessageHeader header; | ||
125 | |||
126 | }; | ||
127 | |||
128 | |||
129 | /** | ||
130 | * UDP NAT Probe message confirm definition | ||
131 | */ | ||
132 | struct UDP_NAT_ProbeMessageConfirmation | ||
133 | { | ||
134 | /** | ||
135 | * Message header | ||
136 | */ | ||
137 | struct GNUNET_MessageHeader header; | ||
138 | |||
139 | }; | ||
140 | |||
141 | |||
142 | |||
143 | /* Forward definition */ | ||
144 | struct Plugin; | ||
145 | |||
146 | struct PrettyPrinterContext | ||
147 | { | ||
148 | GNUNET_TRANSPORT_AddressStringCallback asc; | ||
149 | void *asc_cls; | ||
150 | uint16_t port; | ||
151 | }; | ||
152 | |||
153 | struct MessageQueue | ||
154 | { | ||
155 | /** | ||
156 | * Linked List | ||
157 | */ | ||
158 | struct MessageQueue *next; | ||
159 | |||
160 | /** | ||
161 | * Session this message belongs to | ||
162 | */ | ||
163 | struct PeerSession *session; | ||
164 | |||
165 | /** | ||
166 | * Actual message to be sent | ||
167 | */ | ||
168 | char *msgbuf; | ||
169 | |||
170 | /** | ||
171 | * Size of message buffer to be sent | ||
172 | */ | ||
173 | size_t msgbuf_size; | ||
174 | |||
175 | /** | ||
176 | * When to discard this message | ||
177 | */ | ||
178 | struct GNUNET_TIME_Absolute timeout; | ||
179 | |||
180 | /** | ||
181 | * Continuation to call when this message goes out | ||
182 | */ | ||
183 | GNUNET_TRANSPORT_TransmitContinuation cont; | ||
184 | |||
185 | /** | ||
186 | * closure for continuation | ||
187 | */ | ||
188 | void *cont_cls; | ||
189 | |||
190 | }; | ||
191 | |||
192 | /** | ||
193 | * UDP NAT "Session" | ||
194 | */ | ||
195 | struct PeerSession | ||
196 | { | ||
197 | |||
198 | /** | ||
199 | * Stored in a linked list. | ||
200 | */ | ||
201 | struct PeerSession *next; | ||
202 | |||
203 | /** | ||
204 | * Pointer to the global plugin struct. | ||
205 | */ | ||
206 | struct Plugin *plugin; | ||
207 | |||
208 | /** | ||
209 | * To whom are we talking to (set to our identity | ||
210 | * if we are still waiting for the welcome message) | ||
211 | */ | ||
212 | struct GNUNET_PeerIdentity target; | ||
213 | |||
214 | /** | ||
215 | * Address of the other peer (either based on our 'connect' | ||
216 | * call or on our 'accept' call). | ||
217 | */ | ||
218 | void *connect_addr; | ||
219 | |||
220 | /** | ||
221 | * Length of connect_addr. | ||
222 | */ | ||
223 | size_t connect_alen; | ||
224 | |||
225 | /** | ||
226 | * Are we still expecting the welcome message? (GNUNET_YES/GNUNET_NO) | ||
227 | */ | ||
228 | int expecting_welcome; | ||
229 | |||
230 | /** | ||
231 | * From which socket do we need to send to this peer? | ||
232 | */ | ||
233 | struct GNUNET_NETWORK_Handle *sock; | ||
234 | |||
235 | /* | ||
236 | * Queue of messages for this peer, in the case that | ||
237 | * we have to await a connection... | ||
238 | */ | ||
239 | struct MessageQueue *messages; | ||
240 | |||
241 | }; | ||
242 | |||
243 | |||
244 | struct UDP_NAT_Probes | ||
245 | { | ||
246 | |||
247 | /** | ||
248 | * Linked list | ||
249 | */ | ||
250 | struct UDP_NAT_Probes *next; | ||
251 | |||
252 | /** | ||
253 | * Address string that the server process returned to us | ||
254 | */ | ||
255 | char *address_string; | ||
256 | |||
257 | /** | ||
258 | * Timeout for this set of probes | ||
259 | */ | ||
260 | struct GNUNET_TIME_Absolute timeout; | ||
261 | |||
262 | /** | ||
263 | * Current index (which port to send on next basically) | ||
264 | */ | ||
265 | int index; | ||
266 | |||
267 | /** | ||
268 | * The plugin this probe belongs to | ||
269 | */ | ||
270 | struct Plugin *plugin; | ||
271 | |||
272 | /** | ||
273 | * The task used to send these probes | ||
274 | */ | ||
275 | GNUNET_SCHEDULER_TaskIdentifier task; | ||
276 | |||
277 | /** | ||
278 | * Network address (always ipv4) | ||
279 | */ | ||
280 | struct sockaddr_in sock_addr; | ||
281 | |||
282 | }; | ||
283 | |||
284 | |||
285 | /** | ||
286 | * Encapsulation of all of the state of the plugin. | ||
287 | */ | ||
288 | struct Plugin | ||
289 | { | ||
290 | /** | ||
291 | * Our environment. | ||
292 | */ | ||
293 | struct GNUNET_TRANSPORT_PluginEnvironment *env; | ||
294 | |||
295 | /** | ||
296 | * Handle for the statistics service. | ||
297 | */ | ||
298 | struct GNUNET_STATISTICS_Handle *statistics; | ||
299 | |||
300 | /** | ||
301 | * Handle to the network service. | ||
302 | */ | ||
303 | struct GNUNET_SERVICE_Context *service; | ||
304 | |||
305 | /* | ||
306 | * Session of peers with whom we are currently connected | ||
307 | */ | ||
308 | struct PeerSession *sessions; | ||
309 | |||
310 | /** | ||
311 | * Handle for request of hostname resolution, non-NULL if pending. | ||
312 | */ | ||
313 | struct GNUNET_RESOLVER_RequestHandle *hostname_dns; | ||
314 | |||
315 | /** | ||
316 | * ID of task used to update our addresses when one expires. | ||
317 | */ | ||
318 | GNUNET_SCHEDULER_TaskIdentifier address_update_task; | ||
319 | |||
320 | /** | ||
321 | * ID of select task | ||
322 | */ | ||
323 | GNUNET_SCHEDULER_TaskIdentifier select_task; | ||
324 | |||
325 | /** | ||
326 | * Starting port, will listen on num_ports (if available) starting | ||
327 | * at this number | ||
328 | */ | ||
329 | uint16_t starting_port; | ||
330 | |||
331 | /** | ||
332 | * How many ports should we be using? | ||
333 | */ | ||
334 | uint16_t num_ports; | ||
335 | |||
336 | /* | ||
337 | * The external address given to us by the user. Must be actual | ||
338 | * outside visible address for NAT punching to work. | ||
339 | */ | ||
340 | char *external_address; | ||
341 | |||
342 | /* | ||
343 | * FD Read set | ||
344 | */ | ||
345 | struct GNUNET_NETWORK_FDSet *rs; | ||
346 | |||
347 | /* | ||
348 | * stdout pipe handle for the gnunet-nat-server process | ||
349 | */ | ||
350 | struct GNUNET_DISK_PipeHandle *server_stdout; | ||
351 | |||
352 | /* | ||
353 | * stdout file handle (for reading) for the gnunet-nat-server process | ||
354 | */ | ||
355 | const struct GNUNET_DISK_FileHandle *server_stdout_handle; | ||
356 | |||
357 | /** | ||
358 | * ID of select gnunet-nat-server stdout read task | ||
359 | */ | ||
360 | GNUNET_SCHEDULER_TaskIdentifier server_read_task; | ||
361 | |||
362 | /** | ||
363 | * Is this transport configured to be behind a NAT? | ||
364 | */ | ||
365 | int behind_nat; | ||
366 | |||
367 | /** | ||
368 | * The process id of the server process (if behind NAT) | ||
369 | */ | ||
370 | pid_t server_pid; | ||
371 | |||
372 | /** | ||
373 | * Probes in flight | ||
374 | */ | ||
375 | struct UDP_NAT_Probes *probes; | ||
376 | |||
377 | }; | ||
378 | |||
379 | /* *********** globals ************* */ | ||
380 | |||
381 | /** | ||
382 | * the socket that we transmit all data with | ||
383 | */ | ||
384 | static struct GNUNET_NETWORK_Handle *udp_nat_socks[UDP_NAT_LISTEN_PORTS]; | ||
385 | |||
386 | |||
387 | /** | ||
388 | * Forward declaration. | ||
389 | */ | ||
390 | void | ||
391 | udp_probe_continuation (void *cls, const struct GNUNET_PeerIdentity *target, int result); | ||
392 | |||
393 | |||
394 | /** | ||
395 | * Disconnect from a remote node. | ||
396 | * | ||
397 | * @param tsession the session that is closed | ||
398 | * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed | ||
399 | */ | ||
400 | void | ||
401 | udp_nat_disconnect (void *cls, const struct GNUNET_PeerIdentity *target) | ||
402 | { | ||
403 | return; | ||
404 | } | ||
405 | |||
406 | /** | ||
407 | * Shutdown the server process (stop receiving inbound traffic). Maybe | ||
408 | * restarted later! | ||
409 | */ | ||
410 | static int | ||
411 | udp_nat_transport_server_stop (void *cls) | ||
412 | { | ||
413 | struct Plugin *plugin = cls; | ||
414 | int ret; | ||
415 | int ok; | ||
416 | int i; | ||
417 | |||
418 | if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK) | ||
419 | { | ||
420 | GNUNET_SCHEDULER_cancel (plugin->env->sched, plugin->select_task); | ||
421 | plugin->select_task = GNUNET_SCHEDULER_NO_TASK; | ||
422 | } | ||
423 | |||
424 | for (i = 0; i < plugin->num_ports; i++) | ||
425 | { | ||
426 | ok = GNUNET_NETWORK_socket_close (udp_nat_socks[i]); | ||
427 | if (ok == GNUNET_OK) | ||
428 | udp_nat_socks[i] = NULL; | ||
429 | ret += ok; | ||
430 | } | ||
431 | |||
432 | if (plugin->behind_nat == GNUNET_YES) | ||
433 | { | ||
434 | if (0 != PLIBC_KILL (plugin->server_pid, SIGTERM)) | ||
435 | { | ||
436 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); | ||
437 | } | ||
438 | GNUNET_OS_process_wait (plugin->server_pid); | ||
439 | } | ||
440 | |||
441 | if (ret != GNUNET_OK) | ||
442 | return GNUNET_SYSERR; | ||
443 | return ret; | ||
444 | } | ||
445 | |||
446 | |||
447 | struct PeerSession * | ||
448 | find_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *peer) | ||
449 | { | ||
450 | struct PeerSession *pos; | ||
451 | |||
452 | pos = plugin->sessions; | ||
453 | while (pos != NULL) | ||
454 | { | ||
455 | if (memcmp(&pos->target, peer, sizeof(struct GNUNET_PeerIdentity)) == 0) | ||
456 | return pos; | ||
457 | pos = pos->next; | ||
458 | } | ||
459 | |||
460 | return pos; | ||
461 | } | ||
462 | |||
463 | |||
464 | /** | ||
465 | * Actually send out the message, assume we've got the address and | ||
466 | * send_handle squared away! | ||
467 | * | ||
468 | * @param cls closure | ||
469 | * @param send_handle which handle to send message on | ||
470 | * @param target who should receive this message (ignored by UDP) | ||
471 | * @param msgbuf one or more GNUNET_MessageHeader(s) strung together | ||
472 | * @param msgbufsize the size of the msgbuf to send | ||
473 | * @param priority how important is the message (ignored by UDP) | ||
474 | * @param timeout when should we time out (give up) if we can not transmit? | ||
475 | * @param addr the addr to send the message to, needs to be a sockaddr for us | ||
476 | * @param addrlen the len of addr | ||
477 | * @param cont continuation to call once the message has | ||
478 | * been transmitted (or if the transport is ready | ||
479 | * for the next transmission call; or if the | ||
480 | * peer disconnected...) | ||
481 | * @param cont_cls closure for cont | ||
482 | * | ||
483 | * @return the number of bytes written | ||
484 | * | ||
485 | */ | ||
486 | static ssize_t | ||
487 | udp_nat_real_send (void *cls, | ||
488 | struct GNUNET_NETWORK_Handle *send_handle, | ||
489 | const struct GNUNET_PeerIdentity *target, | ||
490 | const char *msgbuf, | ||
491 | size_t msgbuf_size, | ||
492 | unsigned int priority, | ||
493 | struct GNUNET_TIME_Relative timeout, | ||
494 | const void *addr, | ||
495 | size_t addrlen, | ||
496 | GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) | ||
497 | { | ||
498 | struct Plugin *plugin = cls; | ||
499 | struct UDPMessage *message; | ||
500 | int ssize; | ||
501 | ssize_t sent; | ||
502 | |||
503 | if ((addr == NULL) || (addrlen == 0)) | ||
504 | { | ||
505 | #if DEBUG_UDP_NAT | ||
506 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _ | ||
507 | ("udp_nat_plugin_send called without address, returning!\n")); | ||
508 | #endif | ||
509 | cont (cont_cls, target, GNUNET_SYSERR); | ||
510 | return 0; /* Can never send if we don't have an address!! */ | ||
511 | } | ||
512 | |||
513 | /* Build the message to be sent */ | ||
514 | message = GNUNET_malloc (sizeof (struct UDPMessage) + msgbuf_size); | ||
515 | ssize = sizeof (struct UDPMessage) + msgbuf_size; | ||
516 | |||
517 | #if DEBUG_UDP_NAT | ||
518 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _ | ||
519 | ("In udp_nat_send, ssize is %d, sending message to %s\n"), ssize, GNUNET_a2s((const struct sockaddr *)addr, addrlen)); | ||
520 | #endif | ||
521 | message->header.size = htons (ssize); | ||
522 | message->header.type = htons (0); | ||
523 | memcpy (&message->sender, plugin->env->my_identity, | ||
524 | sizeof (struct GNUNET_PeerIdentity)); | ||
525 | memcpy (&message[1], msgbuf, msgbuf_size); | ||
526 | |||
527 | /* Actually send the message */ | ||
528 | sent = | ||
529 | GNUNET_NETWORK_socket_sendto (send_handle, message, ssize, | ||
530 | addr, | ||
531 | addrlen); | ||
532 | |||
533 | if (cont != NULL) | ||
534 | { | ||
535 | if (sent == GNUNET_SYSERR) | ||
536 | cont (cont_cls, target, GNUNET_SYSERR); | ||
537 | else | ||
538 | { | ||
539 | #if DEBUG_UDP_NAT | ||
540 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _ | ||
541 | ("Successfully sent message, calling transmit continuation!\n")); | ||
542 | #endif | ||
543 | cont (cont_cls, target, GNUNET_OK); | ||
544 | } | ||
545 | } | ||
546 | GNUNET_free (message); | ||
547 | return sent; | ||
548 | } | ||
549 | |||
550 | /** | ||
551 | * We learned about a peer (possibly behind NAT) so run the | ||
552 | * gnunet-nat-client to send a dummy ICMP response | ||
553 | * | ||
554 | * @param plugin the plugin for this transport | ||
555 | * @param addr the address of the peer | ||
556 | * @param addrlen the length of the address | ||
557 | */ | ||
558 | void | ||
559 | run_gnunet_nat_client (struct Plugin *plugin, const char *addr, size_t addrlen) | ||
560 | { | ||
561 | char inet4[INET_ADDRSTRLEN]; | ||
562 | char *address_as_string; | ||
563 | pid_t pid; | ||
564 | const struct sockaddr *sa = (const struct sockaddr *)addr; | ||
565 | |||
566 | if (addrlen < sizeof (struct sockaddr)) | ||
567 | return; | ||
568 | switch (sa->sa_family) | ||
569 | { | ||
570 | case AF_INET: | ||
571 | if (addrlen != sizeof (struct sockaddr_in)) | ||
572 | return; | ||
573 | inet_ntop (AF_INET, | ||
574 | &((struct sockaddr_in *) sa)->sin_addr, | ||
575 | inet4, INET_ADDRSTRLEN); | ||
576 | address_as_string = GNUNET_strdup (inet4); | ||
577 | break; | ||
578 | case AF_INET6: | ||
579 | default: | ||
580 | return; | ||
581 | } | ||
582 | |||
583 | #if DEBUG_UDP_NAT | ||
584 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat", | ||
585 | _("Running gnunet-nat-client with address %s\n"), address_as_string); | ||
586 | #endif | ||
587 | /* Start the server process */ | ||
588 | pid = GNUNET_OS_start_process(NULL, NULL, "gnunet-nat-client", "gnunet-nat-client", plugin->external_address, address_as_string, NULL); | ||
589 | GNUNET_OS_process_wait (pid); | ||
590 | } | ||
591 | |||
592 | /** | ||
593 | * Function that can be used by the transport service to transmit | ||
594 | * a message using the plugin. | ||
595 | * | ||
596 | * @param cls closure | ||
597 | * @param target who should receive this message (ignored by UDP) | ||
598 | * @param msgbuf one or more GNUNET_MessageHeader(s) strung together | ||
599 | * @param msgbufsize the size of the msgbuf to send | ||
600 | * @param priority how important is the message (ignored by UDP) | ||
601 | * @param timeout when should we time out (give up) if we can not transmit? | ||
602 | * @param addr the addr to send the message to, needs to be a sockaddr for us | ||
603 | * @param addrlen the len of addr | ||
604 | * @param force_address not used, we had better have an address to send to | ||
605 | * because we are stateless!! | ||
606 | * @param cont continuation to call once the message has | ||
607 | * been transmitted (or if the transport is ready | ||
608 | * for the next transmission call; or if the | ||
609 | * peer disconnected...) | ||
610 | * @param cont_cls closure for cont | ||
611 | * | ||
612 | * @return the number of bytes written | ||
613 | */ | ||
614 | static ssize_t | ||
615 | udp_nat_plugin_send (void *cls, | ||
616 | const struct GNUNET_PeerIdentity *target, | ||
617 | const char *msgbuf, | ||
618 | size_t msgbuf_size, | ||
619 | unsigned int priority, | ||
620 | struct GNUNET_TIME_Relative timeout, | ||
621 | const void *addr, | ||
622 | size_t addrlen, | ||
623 | int force_address, | ||
624 | GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) | ||
625 | { | ||
626 | struct Plugin *plugin = cls; | ||
627 | ssize_t sent; | ||
628 | struct MessageQueue *temp_message; | ||
629 | struct PeerSession *peer_session; | ||
630 | |||
631 | /** | ||
632 | * FIXME: find which sock in udp_nat_socks to actually send the message on, | ||
633 | * also this means creating some sort of structure to remember target to | ||
634 | * udp sock (or address, or index of udp sock array...) | ||
635 | */ | ||
636 | sent = 0; | ||
637 | if (plugin->behind_nat == GNUNET_NO) | ||
638 | { | ||
639 | peer_session = find_session(plugin, target); | ||
640 | if (peer_session == NULL) /* We have a new peer to add */ | ||
641 | { | ||
642 | /* | ||
643 | * The first time, we can assume we have no knowledge of a | ||
644 | * working port for this peer, call the ICMP message sender | ||
645 | * and wait... | ||
646 | */ | ||
647 | peer_session = GNUNET_malloc(sizeof(struct PeerSession)); | ||
648 | peer_session->connect_addr = GNUNET_malloc(addrlen); | ||
649 | memcpy(peer_session->connect_addr, addr, addrlen); | ||
650 | peer_session->connect_alen = addrlen; | ||
651 | peer_session->plugin = plugin; | ||
652 | peer_session->sock = NULL; | ||
653 | memcpy(&peer_session->target, target, sizeof(struct GNUNET_PeerIdentity)); | ||
654 | peer_session->expecting_welcome = GNUNET_YES; | ||
655 | |||
656 | peer_session->next = plugin->sessions; | ||
657 | plugin->sessions = peer_session; | ||
658 | |||
659 | peer_session->messages = GNUNET_malloc(sizeof(struct MessageQueue)); | ||
660 | peer_session->messages->msgbuf = GNUNET_malloc(msgbuf_size); | ||
661 | memcpy(peer_session->messages->msgbuf, msgbuf, msgbuf_size); | ||
662 | peer_session->messages->msgbuf_size = msgbuf_size; | ||
663 | peer_session->messages->next = NULL; | ||
664 | peer_session->messages->timeout = GNUNET_TIME_relative_to_absolute(timeout); | ||
665 | peer_session->messages->cont = cont; | ||
666 | peer_session->messages->cont_cls = cont_cls; | ||
667 | #if DEBUG_UDP_NAT | ||
668 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat", | ||
669 | _("Set up peer session for peer %s\n"), GNUNET_i2s(target)); | ||
670 | #endif | ||
671 | run_gnunet_nat_client(plugin, addr, addrlen); | ||
672 | |||
673 | } | ||
674 | else | ||
675 | { | ||
676 | if (peer_session->expecting_welcome == GNUNET_NO) /* We are "connected" */ | ||
677 | { | ||
678 | sent = udp_nat_real_send(cls, peer_session->sock, target, msgbuf, msgbuf_size, priority, timeout, peer_session->connect_addr, peer_session->connect_alen, cont, cont_cls); | ||
679 | } | ||
680 | else /* Haven't gotten a response from this peer, queue message */ | ||
681 | { | ||
682 | temp_message = GNUNET_malloc(sizeof(struct MessageQueue)); | ||
683 | temp_message->msgbuf = GNUNET_malloc(msgbuf_size); | ||
684 | memcpy(temp_message->msgbuf, msgbuf, msgbuf_size); | ||
685 | temp_message->msgbuf_size = msgbuf_size; | ||
686 | temp_message->timeout = GNUNET_TIME_relative_to_absolute(timeout); | ||
687 | temp_message->cont = cont; | ||
688 | temp_message->cont_cls = cont_cls; | ||
689 | temp_message->next = peer_session->messages; | ||
690 | peer_session->messages = temp_message; | ||
691 | } | ||
692 | } | ||
693 | } | ||
694 | else /* We are behind a NAT, so we can just send the message as is */ | ||
695 | { | ||
696 | sent = udp_nat_real_send(cls, udp_nat_socks[0], target, msgbuf, msgbuf_size, priority, timeout, addr, addrlen, cont, cont_cls); | ||
697 | } | ||
698 | |||
699 | return sent; | ||
700 | } | ||
701 | |||
702 | |||
703 | /** | ||
704 | * Add the IP of our network interface to the list of | ||
705 | * our external IP addresses. | ||
706 | */ | ||
707 | static int | ||
708 | process_interfaces (void *cls, | ||
709 | const char *name, | ||
710 | int isDefault, | ||
711 | const struct sockaddr *addr, socklen_t addrlen) | ||
712 | { | ||
713 | struct Plugin *plugin = cls; | ||
714 | int af; | ||
715 | struct sockaddr_in *v4; | ||
716 | struct sockaddr_in6 *v6; | ||
717 | |||
718 | /* | ||
719 | * FIXME: Do we want to advertise _all_ of our UDP NAT addresses? | ||
720 | * Probably not. Can we assume that we'll only send these out of band? | ||
721 | * Ostensibly we won't accept just any connection on these ports anyways | ||
722 | * right? | ||
723 | */ | ||
724 | |||
725 | af = addr->sa_family; | ||
726 | if (af == AF_INET) | ||
727 | { | ||
728 | v4 = (struct sockaddr_in *) addr; | ||
729 | v4->sin_port = htons (plugin->starting_port); | ||
730 | } | ||
731 | else | ||
732 | { | ||
733 | GNUNET_assert (af == AF_INET6); | ||
734 | v6 = (struct sockaddr_in6 *) addr; | ||
735 | v6->sin6_port = htons (plugin->starting_port); | ||
736 | } | ||
737 | |||
738 | #if !IPV6 | ||
739 | if (af == AF_INET) | ||
740 | { | ||
741 | #endif | ||
742 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO | | ||
743 | GNUNET_ERROR_TYPE_BULK, | ||
744 | "udp-nat", _("Found address `%s' (%s)\n"), | ||
745 | GNUNET_a2s (addr, addrlen), name); | ||
746 | plugin->env->notify_address (plugin->env->cls, | ||
747 | "udp_nat", | ||
748 | addr, addrlen, GNUNET_TIME_UNIT_FOREVER_REL); | ||
749 | #if !IPV6 | ||
750 | } | ||
751 | #endif | ||
752 | |||
753 | return GNUNET_OK; | ||
754 | } | ||
755 | |||
756 | |||
757 | /** | ||
758 | * Function called by the resolver for each address obtained from DNS | ||
759 | * for our own hostname. Add the addresses to the list of our | ||
760 | * external IP addresses. | ||
761 | * | ||
762 | * @param cls closure | ||
763 | * @param addr one of the addresses of the host, NULL for the last address | ||
764 | * @param addrlen length of the address | ||
765 | */ | ||
766 | static void | ||
767 | process_hostname_ips (void *cls, | ||
768 | const struct sockaddr *addr, socklen_t addrlen) | ||
769 | { | ||
770 | struct Plugin *plugin = cls; | ||
771 | |||
772 | if (addr == NULL) | ||
773 | { | ||
774 | plugin->hostname_dns = NULL; | ||
775 | return; | ||
776 | } | ||
777 | process_interfaces (plugin, "<hostname>", GNUNET_YES, addr, addrlen); | ||
778 | } | ||
779 | |||
780 | |||
781 | /** | ||
782 | * Send UDP probe messages or UDP keepalive messages, depending on the | ||
783 | * state of the connection. | ||
784 | * | ||
785 | * @param cls closure for this call (should be the main Plugin) | ||
786 | * @param tc task context for running this | ||
787 | */ | ||
788 | static void | ||
789 | send_udp_probe_message (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
790 | { | ||
791 | struct UDP_NAT_Probes *probe = cls; | ||
792 | struct UDP_NAT_ProbeMessage *message; | ||
793 | struct Plugin *plugin = probe->plugin; | ||
794 | int sent; | ||
795 | |||
796 | message = GNUNET_malloc(sizeof(struct UDP_NAT_ProbeMessage)); | ||
797 | message->header.size = htons(sizeof(struct UDP_NAT_ProbeMessage)); | ||
798 | message->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE); | ||
799 | //message->port = htons(probe->index + plugin->starting_port); | ||
800 | probe->sock_addr.sin_port = htons(probe->index + plugin->starting_port); | ||
801 | #if DEBUG_UDP_NAT | ||
802 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat", | ||
803 | _("Sending a probe on port %d\n"), ntohs(probe->sock_addr.sin_port)); | ||
804 | #endif | ||
805 | #if DEBUG_UDP_NAT | ||
806 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _ | ||
807 | ("about to send probe, ssize is %d, sending message to %s\n"), ntohs(message->header.size), GNUNET_a2s((const struct sockaddr *)&probe->sock_addr, sizeof(probe->sock_addr))); | ||
808 | #endif | ||
809 | sent = udp_nat_real_send(plugin, udp_nat_socks[probe->index], NULL, (char *)message, ntohs(message->header.size), 0, GNUNET_TIME_relative_get_unit(), &probe->sock_addr, sizeof(probe->sock_addr), &udp_probe_continuation, probe); | ||
810 | |||
811 | if (probe->index + 1 < plugin->num_ports) | ||
812 | probe->index += 1; | ||
813 | else | ||
814 | probe->index = 0; | ||
815 | |||
816 | } | ||
817 | |||
818 | |||
819 | void | ||
820 | dummy_continuation (void *cls, const struct GNUNET_PeerIdentity *target, int result) | ||
821 | { | ||
822 | return; | ||
823 | } | ||
824 | |||
825 | |||
826 | /** | ||
827 | * Continuation for probe sends. If the last probe was sent | ||
828 | * "successfully", schedule sending of another one. If not, | ||
829 | * | ||
830 | */ | ||
831 | void | ||
832 | udp_probe_continuation (void *cls, const struct GNUNET_PeerIdentity *target, int result) | ||
833 | { | ||
834 | struct UDP_NAT_Probes *probe = cls; | ||
835 | struct Plugin *plugin = probe->plugin; | ||
836 | |||
837 | if (result == GNUNET_OK) | ||
838 | { | ||
839 | #if DEBUG_UDP_NAT | ||
840 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat", | ||
841 | _("Successfully sent a probe\n")); | ||
842 | #endif | ||
843 | if (probe->index == 0) | ||
844 | probe->task = GNUNET_SCHEDULER_add_delayed(plugin->env->sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 5000), &send_udp_probe_message, probe); | ||
845 | else | ||
846 | probe->task = GNUNET_SCHEDULER_add_delayed(plugin->env->sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 500), &send_udp_probe_message, probe); | ||
847 | } | ||
848 | else /* Destroy the probe context? */ | ||
849 | { | ||
850 | #if DEBUG_UDP_NAT | ||
851 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat", | ||
852 | _("Sending probe didn't go well...\n")); | ||
853 | #endif | ||
854 | |||
855 | } | ||
856 | } | ||
857 | |||
858 | /** | ||
859 | * Find probe message by address | ||
860 | * | ||
861 | * @param plugin the plugin for this transport | ||
862 | * @param address_string the ip address as a string | ||
863 | */ | ||
864 | struct UDP_NAT_Probes * | ||
865 | find_probe(struct Plugin *plugin, char * address_string) | ||
866 | { | ||
867 | struct UDP_NAT_Probes *pos; | ||
868 | |||
869 | pos = plugin->probes; | ||
870 | while (pos != NULL) | ||
871 | if (strcmp(pos->address_string, address_string) == 0) | ||
872 | return pos; | ||
873 | |||
874 | return pos; | ||
875 | } | ||
876 | |||
877 | |||
878 | /* | ||
879 | * @param cls the plugin handle | ||
880 | * @param tc the scheduling context (for rescheduling this function again) | ||
881 | * | ||
882 | * We have been notified that gnunet-nat-server has written something to stdout. | ||
883 | * Handle the output, then reschedule this function to be called again once | ||
884 | * more is available. | ||
885 | * | ||
886 | */ | ||
887 | static void | ||
888 | udp_nat_plugin_server_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
889 | { | ||
890 | struct Plugin *plugin = cls; | ||
891 | char mybuf[40]; | ||
892 | ssize_t bytes; | ||
893 | memset(&mybuf, 0, sizeof(mybuf)); | ||
894 | int i; | ||
895 | struct UDP_NAT_Probes *temp_probe; | ||
896 | |||
897 | bytes = GNUNET_DISK_file_read(plugin->server_stdout_handle, &mybuf, sizeof(mybuf)); | ||
898 | |||
899 | if (bytes < 1) | ||
900 | { | ||
901 | #if DEBUG_UDP_NAT | ||
902 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat", | ||
903 | _("Finished reading from server stdout with code: %d\n"), bytes); | ||
904 | #endif | ||
905 | return; | ||
906 | } | ||
907 | |||
908 | for (i = 0; i < sizeof(mybuf); i++) | ||
909 | { | ||
910 | if (mybuf[i] == '\n') | ||
911 | mybuf[i] = '\0'; | ||
912 | } | ||
913 | |||
914 | #if DEBUG_UDP_NAT | ||
915 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat", | ||
916 | _("nat-server-read read: %s\n"), &mybuf); | ||
917 | #endif | ||
918 | |||
919 | /* Schedule sending of messages to peer on each open port */ | ||
920 | temp_probe = find_probe(plugin, &mybuf[0]); | ||
921 | |||
922 | if (temp_probe == NULL) | ||
923 | { | ||
924 | temp_probe = GNUNET_malloc(sizeof(struct UDP_NAT_Probes)); | ||
925 | temp_probe->address_string = strdup(&mybuf[0]); | ||
926 | temp_probe->sock_addr.sin_family = AF_INET; | ||
927 | GNUNET_assert(inet_pton(AF_INET, &mybuf[0], &temp_probe->sock_addr.sin_addr) == 1); | ||
928 | temp_probe->index = 0; | ||
929 | temp_probe->next = plugin->probes; | ||
930 | temp_probe->plugin = plugin; | ||
931 | temp_probe->task = GNUNET_SCHEDULER_add_delayed(plugin->env->sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 500), &send_udp_probe_message, temp_probe); | ||
932 | plugin->probes = temp_probe; | ||
933 | } | ||
934 | |||
935 | plugin->server_read_task = | ||
936 | GNUNET_SCHEDULER_add_read_file (plugin->env->sched, | ||
937 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
938 | plugin->server_stdout_handle, &udp_nat_plugin_server_read, plugin); | ||
939 | |||
940 | } | ||
941 | |||
942 | |||
943 | /** | ||
944 | * Demultiplexer for UDP NAT messages | ||
945 | * | ||
946 | * @param plugin the main plugin for this transport | ||
947 | * | ||
948 | */ | ||
949 | static void | ||
950 | udp_nat_demultiplexer(struct Plugin *plugin, struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *currhdr, struct sockaddr_storage *sender_addr, socklen_t fromlen, int receiving_port) | ||
951 | { | ||
952 | struct UDP_NAT_ProbeMessageReply *outgoing_probe_reply; | ||
953 | struct UDP_NAT_ProbeMessageConfirmation *outgoing_probe_confirmation; | ||
954 | |||
955 | struct UDP_NAT_ProbeMessage *incoming_probe; | ||
956 | struct UDP_NAT_ProbeMessageReply *incoming_probe_reply; | ||
957 | struct UDP_NAT_ProbeMessageConfirmation *incoming_probe_confirmation; | ||
958 | char addr_buf[INET_ADDRSTRLEN]; | ||
959 | struct UDP_NAT_Probes *outgoing_probe; | ||
960 | struct PeerSession *peer_session; | ||
961 | struct MessageQueue *pending_message; | ||
962 | struct MessageQueue *pending_message_temp; | ||
963 | int sent; | ||
964 | |||
965 | switch (ntohs(currhdr->type)) | ||
966 | { | ||
967 | case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE: | ||
968 | /* Send probe reply */ | ||
969 | incoming_probe = (struct UDP_NAT_ProbeMessage *)currhdr; | ||
970 | outgoing_probe_reply = GNUNET_malloc(sizeof(struct UDP_NAT_ProbeMessageReply)); | ||
971 | outgoing_probe_reply->header.size = htons(sizeof(struct UDP_NAT_ProbeMessageReply)); | ||
972 | outgoing_probe_reply->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_REPLY); | ||
973 | |||
974 | #if DEBUG_UDP_NAT | ||
975 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat", | ||
976 | _("Received a probe from port %d, sent_from port %d\n"), receiving_port, ((struct sockaddr_in *)sender_addr)->sin_port); | ||
977 | #endif | ||
978 | |||
979 | sent = udp_nat_real_send(plugin, udp_nat_socks[0], NULL, (char *)outgoing_probe_reply, ntohs(outgoing_probe_reply->header.size), 0, GNUNET_TIME_relative_get_unit(), sender_addr, fromlen, &dummy_continuation, NULL); | ||
980 | #if DEBUG_UDP_NAT | ||
981 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat", | ||
982 | _("Sent %d byes of PROBE REPLY\n"), sent); | ||
983 | #endif | ||
984 | |||
985 | break; | ||
986 | case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_REPLY: | ||
987 | /* Check for existing probe, check ports returned, send confirmation if all is well */ | ||
988 | incoming_probe_reply = (struct UDP_NAT_ProbeMessageReply *)currhdr; | ||
989 | #if DEBUG_UDP_NAT | ||
990 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp-nat", | ||
991 | _("Received a probe reply with ss_family %d!\n"), sender_addr->ss_family); | ||
992 | #endif | ||
993 | /* FIXME: use nonce, then IPv6 replies could work I think... */ | ||
994 | if (sender_addr->ss_family == AF_INET) | ||
995 | { | ||
996 | memset(&addr_buf, 0, sizeof(addr_buf)); | ||
997 | inet_ntop(AF_INET, &((struct sockaddr_in *) sender_addr)->sin_addr, addr_buf, INET_ADDRSTRLEN); | ||
998 | outgoing_probe = find_probe(plugin, &addr_buf[0]); | ||
999 | if (outgoing_probe != NULL) | ||
1000 | { | ||
1001 | #if DEBUG_UDP_NAT | ||
1002 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat", | ||
1003 | _("Sending confirmation that were were reached!\n")); | ||
1004 | #endif | ||
1005 | outgoing_probe_confirmation = GNUNET_malloc(sizeof(struct UDP_NAT_ProbeMessageConfirmation)); | ||
1006 | outgoing_probe_confirmation->header.size = htons(sizeof(struct UDP_NAT_ProbeMessageConfirmation)); | ||
1007 | outgoing_probe_confirmation->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_CONFIRM); | ||
1008 | sent = udp_nat_real_send(plugin, udp_nat_socks[receiving_port - plugin->starting_port], NULL, (char *)outgoing_probe_confirmation, ntohs(outgoing_probe_confirmation->header.size), 0, GNUNET_TIME_relative_get_unit(), sender_addr, fromlen, &dummy_continuation, NULL); | ||
1009 | if (outgoing_probe->task != GNUNET_SCHEDULER_NO_TASK) | ||
1010 | { | ||
1011 | GNUNET_SCHEDULER_cancel(plugin->env->sched, outgoing_probe->task); | ||
1012 | outgoing_probe->task = GNUNET_SCHEDULER_NO_TASK; | ||
1013 | /* Schedule task to timeout and remove probe if confirmation not received */ | ||
1014 | } | ||
1015 | } | ||
1016 | else | ||
1017 | { | ||
1018 | #if DEBUG_UDP_NAT | ||
1019 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp-nat", | ||
1020 | _("Received a probe reply, but have no record of a sent probe!\n")); | ||
1021 | #endif | ||
1022 | } | ||
1023 | } | ||
1024 | break; | ||
1025 | case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_CONFIRM: | ||
1026 | incoming_probe_confirmation = (struct UDP_NAT_ProbeMessageConfirmation *)currhdr; | ||
1027 | peer_session = find_session(plugin, sender); | ||
1028 | #if DEBUG_UDP_NAT | ||
1029 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat", | ||
1030 | _("Looking up peer session for peer %s\n"), GNUNET_i2s(sender)); | ||
1031 | #endif | ||
1032 | if (peer_session == NULL) /* Shouldn't this NOT happen? */ | ||
1033 | { | ||
1034 | #if DEBUG_UDP_NAT | ||
1035 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp-nat", | ||
1036 | _("Received a probe confirmation, but don't remember this peer!\n")); | ||
1037 | #endif | ||
1038 | } | ||
1039 | else if (peer_session->expecting_welcome == GNUNET_YES) | ||
1040 | { | ||
1041 | peer_session->expecting_welcome = GNUNET_NO; | ||
1042 | peer_session->sock = udp_nat_socks[receiving_port - plugin->starting_port]; /* This may matter, not sure right now... */ | ||
1043 | ((struct sockaddr_in *)peer_session->connect_addr)->sin_port = ((struct sockaddr_in *) sender_addr)->sin_port; | ||
1044 | #if DEBUG_UDP_NAT | ||
1045 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp-nat", | ||
1046 | _("Received a probe confirmation, will send to peer on port %d\n"), ntohs(((struct sockaddr_in *)peer_session->connect_addr)->sin_port)); | ||
1047 | #endif | ||
1048 | if (peer_session->messages != NULL) | ||
1049 | { | ||
1050 | #if DEBUG_UDP_NAT | ||
1051 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp-nat", | ||
1052 | _("Received a probe confirmation, sending queued messages.\n")); | ||
1053 | #endif | ||
1054 | pending_message = peer_session->messages; | ||
1055 | while (pending_message != NULL) | ||
1056 | { | ||
1057 | udp_nat_real_send(plugin, peer_session->sock, &peer_session->target, pending_message->msgbuf, pending_message->msgbuf_size, 0, GNUNET_TIME_relative_get_unit(), peer_session->connect_addr, peer_session->connect_alen, &dummy_continuation, NULL); | ||
1058 | pending_message_temp = pending_message; | ||
1059 | pending_message = pending_message->next; | ||
1060 | GNUNET_free(pending_message_temp->msgbuf); | ||
1061 | GNUNET_free(pending_message_temp); | ||
1062 | } | ||
1063 | } | ||
1064 | |||
1065 | } | ||
1066 | else | ||
1067 | { | ||
1068 | #if DEBUG_UDP_NAT | ||
1069 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp-nat", | ||
1070 | _("Received probe confirmation for already confirmed peer!\n")); | ||
1071 | #endif | ||
1072 | } | ||
1073 | /* Received confirmation, add peer with address/port specified */ | ||
1074 | break; | ||
1075 | case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_KEEPALIVE: | ||
1076 | /* Once we've sent NAT_PROBE_CONFIRM change to sending keepalives */ | ||
1077 | /* If we receive these just ignore! */ | ||
1078 | break; | ||
1079 | default: | ||
1080 | plugin->env->receive (plugin->env->cls, sender, currhdr, UDP_DIRECT_DISTANCE, (char *)sender_addr, fromlen); | ||
1081 | } | ||
1082 | |||
1083 | } | ||
1084 | |||
1085 | |||
1086 | /* | ||
1087 | * @param cls the plugin handle | ||
1088 | * @param tc the scheduling context (for rescheduling this function again) | ||
1089 | * | ||
1090 | * We have been notified that our writeset has something to read. We don't | ||
1091 | * know which socket needs to be read, so we have to check each one | ||
1092 | * Then reschedule this function to be called again once more is available. | ||
1093 | * | ||
1094 | */ | ||
1095 | static void | ||
1096 | udp_nat_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1097 | { | ||
1098 | struct Plugin *plugin = cls; | ||
1099 | char *buf; | ||
1100 | struct UDPMessage *msg; | ||
1101 | const struct GNUNET_MessageHeader *hdr; | ||
1102 | struct GNUNET_PeerIdentity *sender; | ||
1103 | unsigned int buflen; | ||
1104 | socklen_t fromlen; | ||
1105 | struct sockaddr_storage addr; | ||
1106 | ssize_t ret; | ||
1107 | int offset; | ||
1108 | int count; | ||
1109 | int tsize; | ||
1110 | int i; | ||
1111 | char *msgbuf; | ||
1112 | const struct GNUNET_MessageHeader *currhdr; | ||
1113 | |||
1114 | buf = NULL; | ||
1115 | sender = NULL; | ||
1116 | |||
1117 | for (i = 0; i < plugin->num_ports; i++) | ||
1118 | { | ||
1119 | buflen = GNUNET_NETWORK_socket_recvfrom_amount (udp_nat_socks[i]); | ||
1120 | |||
1121 | if (buflen == GNUNET_NO) | ||
1122 | break; | ||
1123 | |||
1124 | buf = GNUNET_malloc (buflen); | ||
1125 | fromlen = sizeof (addr); | ||
1126 | memset (&addr, 0, fromlen); | ||
1127 | ret = | ||
1128 | GNUNET_NETWORK_socket_recvfrom (udp_nat_socks[i], buf, buflen, | ||
1129 | (struct sockaddr *) &addr, &fromlen); | ||
1130 | |||
1131 | #if DEBUG_UDP_NAT | ||
1132 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp-nat", _ | ||
1133 | ("socket_recv returned %u, src_addr_len is %u\n"), ret, | ||
1134 | fromlen); | ||
1135 | #endif | ||
1136 | |||
1137 | if (ret <= 0) | ||
1138 | { | ||
1139 | GNUNET_free (buf); | ||
1140 | break; | ||
1141 | } | ||
1142 | msg = (struct UDPMessage *) buf; | ||
1143 | |||
1144 | #if DEBUG_UDP_NAT | ||
1145 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _ | ||
1146 | ("header reports message size of %d, type %d\n"), | ||
1147 | ntohs (msg->header.size), ntohs (msg->header.type)); | ||
1148 | #endif | ||
1149 | if (ntohs (msg->header.size) < sizeof (struct UDPMessage)) | ||
1150 | { | ||
1151 | GNUNET_free (buf); | ||
1152 | break; | ||
1153 | } | ||
1154 | hdr = (const struct GNUNET_MessageHeader *) &msg[1]; | ||
1155 | msgbuf = (char *)&msg[1]; | ||
1156 | sender = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); | ||
1157 | memcpy (sender, &msg->sender, sizeof (struct GNUNET_PeerIdentity)); | ||
1158 | |||
1159 | offset = 0; | ||
1160 | count = 0; | ||
1161 | tsize = ntohs (msg->header.size) - sizeof(struct UDPMessage); | ||
1162 | |||
1163 | while (offset < tsize) | ||
1164 | { | ||
1165 | currhdr = (struct GNUNET_MessageHeader *)&msgbuf[offset]; | ||
1166 | #if DEBUG_UDP_NAT | ||
1167 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _ | ||
1168 | ("processing msg %d: type %d, size %d at offset %d\n"), | ||
1169 | count, ntohs(currhdr->type), ntohs(currhdr->size), offset); | ||
1170 | #endif | ||
1171 | udp_nat_demultiplexer(plugin, sender, currhdr, &addr, fromlen, plugin->starting_port + i); | ||
1172 | |||
1173 | offset += ntohs(currhdr->size); | ||
1174 | count++; | ||
1175 | } | ||
1176 | } | ||
1177 | |||
1178 | GNUNET_free_non_null (sender); | ||
1179 | GNUNET_free_non_null (buf); | ||
1180 | |||
1181 | plugin->select_task = | ||
1182 | GNUNET_SCHEDULER_add_select (plugin->env->sched, | ||
1183 | GNUNET_SCHEDULER_PRIORITY_DEFAULT, | ||
1184 | GNUNET_SCHEDULER_NO_TASK, | ||
1185 | GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs, | ||
1186 | NULL, &udp_nat_plugin_select, plugin); | ||
1187 | |||
1188 | } | ||
1189 | |||
1190 | /** | ||
1191 | * Create a slew of UDP sockets. If possible, use IPv6, otherwise | ||
1192 | * try IPv4. | ||
1193 | * | ||
1194 | * @param cls closure for server start, should be a struct Plugin * | ||
1195 | * | ||
1196 | * @return number of sockets created or GNUNET_SYSERR on error | ||
1197 | */ | ||
1198 | static int | ||
1199 | udp_nat_transport_server_start (void *cls) | ||
1200 | { | ||
1201 | struct Plugin *plugin = cls; | ||
1202 | struct sockaddr_in serverAddrv4; | ||
1203 | #if IPV6 | ||
1204 | struct sockaddr_in6 serverAddrv6; | ||
1205 | #endif | ||
1206 | struct sockaddr *serverAddr; | ||
1207 | socklen_t addrlen; | ||
1208 | int i; | ||
1209 | int sockets_created; | ||
1210 | |||
1211 | /* Pipe to read from started processes stdout (on read end) */ | ||
1212 | plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES); | ||
1213 | |||
1214 | sockets_created = 0; | ||
1215 | if (plugin->server_stdout == NULL) | ||
1216 | return sockets_created; | ||
1217 | |||
1218 | if (plugin->behind_nat == GNUNET_YES) | ||
1219 | { | ||
1220 | #if DEBUG_UDP_NAT | ||
1221 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
1222 | "udp_nat", | ||
1223 | "Starting gnunet-nat-server process\n"); | ||
1224 | #endif | ||
1225 | /* Start the server process */ | ||
1226 | plugin->server_pid = GNUNET_OS_start_process(NULL, plugin->server_stdout, "gnunet-nat-server", "gnunet-nat-server", plugin->external_address, NULL); | ||
1227 | if (plugin->server_pid == GNUNET_SYSERR) | ||
1228 | return GNUNET_SYSERR; | ||
1229 | /* Close the write end of the read pipe */ | ||
1230 | GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE); | ||
1231 | |||
1232 | plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout, GNUNET_DISK_PIPE_END_READ); | ||
1233 | plugin->server_read_task = | ||
1234 | GNUNET_SCHEDULER_add_read_file (plugin->env->sched, | ||
1235 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1236 | plugin->server_stdout_handle, &udp_nat_plugin_server_read, plugin); | ||
1237 | } | ||
1238 | |||
1239 | /* Open all our sockets for reading/writing */ | ||
1240 | for (i = 0; i < plugin->num_ports; i++) | ||
1241 | { | ||
1242 | udp_nat_socks[i] = NULL; | ||
1243 | #if IPV6 | ||
1244 | if (GNUNET_YES != | ||
1245 | GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, "GNUNETD", | ||
1246 | "DISABLE-IPV6")) | ||
1247 | { | ||
1248 | udp_nat_socks[i] = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 17); | ||
1249 | if (udp_nat_socks[i] != NULL) | ||
1250 | { | ||
1251 | memset (&serverAddrv6, 0, sizeof (serverAddrv6)); | ||
1252 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
1253 | serverAddrv6.sin6_len = sizeof (serverAddrv6); | ||
1254 | #endif | ||
1255 | serverAddrv6.sin6_family = AF_INET6; | ||
1256 | serverAddrv6.sin6_addr = in6addr_any; | ||
1257 | serverAddrv6.sin6_port = htons (i + plugin->starting_port); | ||
1258 | addrlen = sizeof (serverAddrv6); | ||
1259 | serverAddr = (struct sockaddr *) &serverAddrv6; | ||
1260 | } | ||
1261 | } | ||
1262 | #endif | ||
1263 | if (NULL == udp_nat_socks[i]) | ||
1264 | { | ||
1265 | udp_nat_socks[i] = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 17); | ||
1266 | if (NULL == udp_nat_socks[i]) | ||
1267 | { | ||
1268 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp-nat", "socket"); | ||
1269 | return sockets_created; | ||
1270 | } | ||
1271 | else | ||
1272 | { | ||
1273 | memset (&serverAddrv4, 0, sizeof (serverAddrv4)); | ||
1274 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
1275 | serverAddrv4.sin_len = sizeof (serverAddrv4); | ||
1276 | #endif | ||
1277 | serverAddrv4.sin_family = AF_INET; | ||
1278 | serverAddrv4.sin_addr.s_addr = INADDR_ANY; | ||
1279 | if (i == 0) | ||
1280 | serverAddrv4.sin_port = htons (plugin->starting_port); | ||
1281 | else | ||
1282 | serverAddrv4.sin_port = htons (GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, 64537) + 1000); /* Find a non-root port */ | ||
1283 | addrlen = sizeof (serverAddrv4); | ||
1284 | serverAddr = (struct sockaddr *) &serverAddrv4; | ||
1285 | } | ||
1286 | } | ||
1287 | |||
1288 | if (udp_nat_socks[i] != NULL) | ||
1289 | { | ||
1290 | #if DEBUG_UDP_NAT | ||
1291 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
1292 | "udp_nat", | ||
1293 | "Binding to port %d\n", ntohs(serverAddrv4.sin_port)); | ||
1294 | #endif | ||
1295 | while (GNUNET_NETWORK_socket_bind (udp_nat_socks[i], serverAddr, addrlen) != | ||
1296 | GNUNET_OK) | ||
1297 | { | ||
1298 | serverAddrv4.sin_port = htons (GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, 64537) + 1000); /* Find a non-root port */ | ||
1299 | #if DEBUG_UDP_NAT | ||
1300 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
1301 | "udp_nat", | ||
1302 | "Binding failed, trying new port %d\n", ntohs(serverAddrv4.sin_port)); | ||
1303 | #endif | ||
1304 | } | ||
1305 | sockets_created++; | ||
1306 | } | ||
1307 | } | ||
1308 | |||
1309 | plugin->rs = GNUNET_NETWORK_fdset_create (); | ||
1310 | |||
1311 | GNUNET_NETWORK_fdset_zero (plugin->rs); | ||
1312 | |||
1313 | for (i = 0; i < plugin->num_ports; i++) | ||
1314 | { | ||
1315 | GNUNET_NETWORK_fdset_set (plugin->rs, udp_nat_socks[i]); | ||
1316 | } | ||
1317 | |||
1318 | plugin->select_task = | ||
1319 | GNUNET_SCHEDULER_add_select (plugin->env->sched, | ||
1320 | GNUNET_SCHEDULER_PRIORITY_DEFAULT, | ||
1321 | GNUNET_SCHEDULER_NO_TASK, | ||
1322 | GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs, | ||
1323 | NULL, &udp_nat_plugin_select, plugin); | ||
1324 | |||
1325 | return sockets_created; | ||
1326 | } | ||
1327 | |||
1328 | |||
1329 | /** | ||
1330 | * Check if the given port is plausible (must be either | ||
1331 | * our listen port or our advertised port). If it is | ||
1332 | * neither, we return one of these two ports at random. | ||
1333 | * | ||
1334 | * @return either in_port or a more plausible port | ||
1335 | */ | ||
1336 | static uint16_t | ||
1337 | check_port (struct Plugin *plugin, uint16_t in_port) | ||
1338 | { | ||
1339 | int i; | ||
1340 | |||
1341 | for (i = plugin->starting_port; i < plugin->num_ports + plugin->starting_port; i++) | ||
1342 | { | ||
1343 | if (in_port == i) | ||
1344 | return in_port; | ||
1345 | } | ||
1346 | |||
1347 | return GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
1348 | plugin->num_ports) + plugin->starting_port; | ||
1349 | } | ||
1350 | |||
1351 | |||
1352 | /** | ||
1353 | * Another peer has suggested an address for this peer and transport | ||
1354 | * plugin. Check that this could be a valid address. This function | ||
1355 | * is not expected to 'validate' the address in the sense of trying to | ||
1356 | * connect to it but simply to see if the binary format is technically | ||
1357 | * legal for establishing a connection. | ||
1358 | * | ||
1359 | * @param addr pointer to the address, may be modified (slightly) | ||
1360 | * @param addrlen length of addr | ||
1361 | * @return GNUNET_OK if this is a plausible address for this peer | ||
1362 | * and transport, GNUNET_SYSERR if not | ||
1363 | * | ||
1364 | * TODO: perhaps make everything work with sockaddr_storage, it may | ||
1365 | * be a cleaner way to handle addresses in UDP | ||
1366 | */ | ||
1367 | static int | ||
1368 | udp_nat_check_address (void *cls, void *addr, size_t addrlen) | ||
1369 | { | ||
1370 | struct Plugin *plugin = cls; | ||
1371 | char buf[sizeof (struct sockaddr_in6)]; | ||
1372 | |||
1373 | struct sockaddr_in *v4; | ||
1374 | struct sockaddr_in6 *v6; | ||
1375 | |||
1376 | #if IPV6 | ||
1377 | if ((addrlen != sizeof (struct sockaddr_in)) && | ||
1378 | (addrlen != sizeof (struct sockaddr_in6))) | ||
1379 | #else | ||
1380 | if (addrlen != sizeof (struct sockaddr_in)) | ||
1381 | #endif | ||
1382 | { | ||
1383 | GNUNET_break_op (0); | ||
1384 | return GNUNET_SYSERR; | ||
1385 | } | ||
1386 | memcpy (buf, addr, sizeof (struct sockaddr_in6)); | ||
1387 | if (addrlen == sizeof (struct sockaddr_in)) | ||
1388 | { | ||
1389 | v4 = (struct sockaddr_in *) buf; | ||
1390 | v4->sin_port = htons (check_port (plugin, ntohs (v4->sin_port))); | ||
1391 | } | ||
1392 | else | ||
1393 | { | ||
1394 | v6 = (struct sockaddr_in6 *) buf; | ||
1395 | v6->sin6_port = htons (check_port (plugin, ntohs (v6->sin6_port))); | ||
1396 | } | ||
1397 | #if DEBUG_UDP_NAT | ||
1398 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
1399 | "udp_nat", | ||
1400 | "Informing transport service about my address `%s'.\n", | ||
1401 | GNUNET_a2s (addr, addrlen)); | ||
1402 | #endif | ||
1403 | return GNUNET_OK; | ||
1404 | } | ||
1405 | |||
1406 | |||
1407 | /** | ||
1408 | * Append our port and forward the result. | ||
1409 | */ | ||
1410 | static void | ||
1411 | append_port (void *cls, const char *hostname) | ||
1412 | { | ||
1413 | struct PrettyPrinterContext *ppc = cls; | ||
1414 | char *ret; | ||
1415 | |||
1416 | if (hostname == NULL) | ||
1417 | { | ||
1418 | ppc->asc (ppc->asc_cls, NULL); | ||
1419 | GNUNET_free (ppc); | ||
1420 | return; | ||
1421 | } | ||
1422 | GNUNET_asprintf (&ret, "%s:%d", hostname, ppc->port); | ||
1423 | ppc->asc (ppc->asc_cls, ret); | ||
1424 | GNUNET_free (ret); | ||
1425 | } | ||
1426 | |||
1427 | |||
1428 | /** | ||
1429 | * Convert the transports address to a nice, human-readable | ||
1430 | * format. | ||
1431 | * | ||
1432 | * @param cls closure | ||
1433 | * @param type name of the transport that generated the address | ||
1434 | * @param addr one of the addresses of the host, NULL for the last address | ||
1435 | * the specific address format depends on the transport | ||
1436 | * @param addrlen length of the address | ||
1437 | * @param numeric should (IP) addresses be displayed in numeric form? | ||
1438 | * @param timeout after how long should we give up? | ||
1439 | * @param asc function to call on each string | ||
1440 | * @param asc_cls closure for asc | ||
1441 | */ | ||
1442 | static void | ||
1443 | udp_nat_plugin_address_pretty_printer (void *cls, | ||
1444 | const char *type, | ||
1445 | const void *addr, | ||
1446 | size_t addrlen, | ||
1447 | int numeric, | ||
1448 | struct GNUNET_TIME_Relative timeout, | ||
1449 | GNUNET_TRANSPORT_AddressStringCallback asc, | ||
1450 | void *asc_cls) | ||
1451 | { | ||
1452 | struct Plugin *plugin = cls; | ||
1453 | const struct sockaddr_in *v4; | ||
1454 | const struct sockaddr_in6 *v6; | ||
1455 | struct PrettyPrinterContext *ppc; | ||
1456 | |||
1457 | if ((addrlen != sizeof (struct sockaddr_in)) && | ||
1458 | (addrlen != sizeof (struct sockaddr_in6))) | ||
1459 | { | ||
1460 | /* invalid address */ | ||
1461 | GNUNET_break_op (0); | ||
1462 | asc (asc_cls, NULL); | ||
1463 | return; | ||
1464 | } | ||
1465 | ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext)); | ||
1466 | ppc->asc = asc; | ||
1467 | ppc->asc_cls = asc_cls; | ||
1468 | if (addrlen == sizeof (struct sockaddr_in)) | ||
1469 | { | ||
1470 | v4 = (const struct sockaddr_in *) addr; | ||
1471 | ppc->port = ntohs (v4->sin_port); | ||
1472 | } | ||
1473 | else | ||
1474 | { | ||
1475 | v6 = (const struct sockaddr_in6 *) addr; | ||
1476 | ppc->port = ntohs (v6->sin6_port); | ||
1477 | |||
1478 | } | ||
1479 | GNUNET_RESOLVER_hostname_get (plugin->env->sched, | ||
1480 | plugin->env->cfg, | ||
1481 | addr, | ||
1482 | addrlen, | ||
1483 | !numeric, timeout, &append_port, ppc); | ||
1484 | } | ||
1485 | |||
1486 | /** | ||
1487 | * Set a quota for receiving data from the given peer; this is a | ||
1488 | * per-transport limit. This call has no meaning for UDP, as if | ||
1489 | * we don't receive data it still comes in. UDP has no friendliness | ||
1490 | * guarantees, and our buffers will fill at some level. | ||
1491 | * | ||
1492 | * @param cls closure | ||
1493 | * @param target the peer for whom the quota is given | ||
1494 | * @param quota_in quota for receiving/sending data in bytes per ms | ||
1495 | */ | ||
1496 | static void | ||
1497 | udp_nat_plugin_set_receive_quota (void *cls, | ||
1498 | const struct GNUNET_PeerIdentity *target, | ||
1499 | uint32_t quota_in) | ||
1500 | { | ||
1501 | return; /* Do nothing */ | ||
1502 | } | ||
1503 | |||
1504 | /** | ||
1505 | * The exported method. Makes the core api available via a global and | ||
1506 | * returns the udp transport API. | ||
1507 | */ | ||
1508 | void * | ||
1509 | libgnunet_plugin_transport_udp_nat_init (void *cls) | ||
1510 | { | ||
1511 | unsigned long long mtu; | ||
1512 | |||
1513 | struct GNUNET_TRANSPORT_PluginEnvironment *env = cls; | ||
1514 | struct GNUNET_TRANSPORT_PluginFunctions *api; | ||
1515 | struct Plugin *plugin; | ||
1516 | struct GNUNET_SERVICE_Context *service; | ||
1517 | int sockets_created; | ||
1518 | int behind_nat; | ||
1519 | |||
1520 | char *external_address; | ||
1521 | char *starting_port; | ||
1522 | |||
1523 | service = GNUNET_SERVICE_start ("transport-udp-nat", env->sched, env->cfg); | ||
1524 | if (service == NULL) | ||
1525 | { | ||
1526 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "udp_nat", _ | ||
1527 | ("Failed to start service for `%s' transport plugin.\n"), | ||
1528 | "udp-nat"); | ||
1529 | return NULL; | ||
1530 | } | ||
1531 | |||
1532 | if (GNUNET_OK != | ||
1533 | GNUNET_CONFIGURATION_get_value_string (env->cfg, | ||
1534 | "transport-udp-nat", | ||
1535 | "EXTERNAL_ADDRESS", | ||
1536 | &external_address)) | ||
1537 | { | ||
1538 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, | ||
1539 | "udp_nat", | ||
1540 | _ | ||
1541 | ("Require EXTERNAL_ADDRESS for service `%s' in configuration!\n"), | ||
1542 | "transport-udp"); | ||
1543 | GNUNET_SERVICE_stop (service); | ||
1544 | } | ||
1545 | |||
1546 | if (GNUNET_NO == GNUNET_CONFIGURATION_get_value_yesno (env->cfg, | ||
1547 | "transport-udp-nat", | ||
1548 | "BEHIND_NAT")) | ||
1549 | behind_nat = GNUNET_NO; /* We are not behind nat, or so says the user! */ | ||
1550 | else | ||
1551 | behind_nat = GNUNET_YES; /* Assume we are behind nat (default) */ | ||
1552 | |||
1553 | GNUNET_CONFIGURATION_get_value_string (env->cfg, | ||
1554 | "transport-udp-nat", | ||
1555 | "STARTING_PORT", | ||
1556 | &starting_port); | ||
1557 | |||
1558 | mtu = 1240; | ||
1559 | if (mtu < 1200) | ||
1560 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, | ||
1561 | "udp_nat", | ||
1562 | _("MTU %llu for `%s' is probably too low!\n"), mtu, | ||
1563 | "UDP"); | ||
1564 | |||
1565 | plugin = GNUNET_malloc (sizeof (struct Plugin)); | ||
1566 | plugin->external_address = external_address; | ||
1567 | if (starting_port != NULL) | ||
1568 | plugin->starting_port = atoi(starting_port); | ||
1569 | else | ||
1570 | plugin->starting_port = UDP_NAT_STARTING_PORT; | ||
1571 | plugin->behind_nat = behind_nat; | ||
1572 | if (plugin->behind_nat == GNUNET_NO) | ||
1573 | plugin->num_ports = 1; /* Only use one port/socket */ | ||
1574 | else | ||
1575 | plugin->num_ports = UDP_NAT_LISTEN_PORTS; | ||
1576 | |||
1577 | plugin->env = env; | ||
1578 | plugin->statistics = NULL; | ||
1579 | api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions)); | ||
1580 | api->cls = plugin; | ||
1581 | |||
1582 | api->send = &udp_nat_plugin_send; | ||
1583 | api->disconnect = &udp_nat_disconnect; | ||
1584 | api->address_pretty_printer = &udp_nat_plugin_address_pretty_printer; | ||
1585 | api->set_receive_quota = &udp_nat_plugin_set_receive_quota; | ||
1586 | api->check_address = &udp_nat_check_address; | ||
1587 | |||
1588 | plugin->service = service; | ||
1589 | |||
1590 | /* FIXME: do the two calls below periodically again and | ||
1591 | not just once (since the info we get might change...) */ | ||
1592 | GNUNET_OS_network_interfaces_list (&process_interfaces, plugin); | ||
1593 | plugin->hostname_dns = GNUNET_RESOLVER_hostname_resolve (env->sched, | ||
1594 | env->cfg, | ||
1595 | AF_UNSPEC, | ||
1596 | HOSTNAME_RESOLVE_TIMEOUT, | ||
1597 | &process_hostname_ips, | ||
1598 | plugin); | ||
1599 | |||
1600 | sockets_created = udp_nat_transport_server_start (plugin); | ||
1601 | |||
1602 | GNUNET_assert (sockets_created == plugin->num_ports); | ||
1603 | |||
1604 | return api; | ||
1605 | } | ||
1606 | |||
1607 | void * | ||
1608 | libgnunet_plugin_transport_udp_nat_done (void *cls) | ||
1609 | { | ||
1610 | struct GNUNET_TRANSPORT_PluginFunctions *api = cls; | ||
1611 | struct Plugin *plugin = api->cls; | ||
1612 | |||
1613 | udp_nat_transport_server_stop (plugin); | ||
1614 | if (NULL != hostname_dns) | ||
1615 | { | ||
1616 | GNUNET_RESOLVER_request_cancel (hostname_dns); | ||
1617 | hostname_dns = NULL; | ||
1618 | } | ||
1619 | GNUNET_SERVICE_stop (plugin->service); | ||
1620 | |||
1621 | GNUNET_NETWORK_fdset_destroy (plugin->rs); | ||
1622 | GNUNET_free (plugin); | ||
1623 | GNUNET_free (api); | ||
1624 | return NULL; | ||
1625 | } | ||
1626 | |||
1627 | /* end of plugin_transport_udp.c */ | ||
diff --git a/src/transport/test_transport_api.c b/src/transport/test_transport_api.c index a43f971a0..2db990e82 100644 --- a/src/transport/test_transport_api.c +++ b/src/transport/test_transport_api.c | |||
@@ -19,7 +19,12 @@ | |||
19 | */ | 19 | */ |
20 | /** | 20 | /** |
21 | * @file transport/test_transport_api.c | 21 | * @file transport/test_transport_api.c |
22 | * @brief testcase for transport_api.c | 22 | * @brief base test case for transport implementations |
23 | * | ||
24 | * This test case serves as a base for tcp, udp, and udp-nat | ||
25 | * transport test cases. Based on the executable being run | ||
26 | * the correct test case will be performed. Conservation of | ||
27 | * C code apparently. | ||
23 | */ | 28 | */ |
24 | #include "platform.h" | 29 | #include "platform.h" |
25 | #include "gnunet_common.h" | 30 | #include "gnunet_common.h" |
@@ -31,14 +36,12 @@ | |||
31 | #include "gnunet_transport_service.h" | 36 | #include "gnunet_transport_service.h" |
32 | #include "transport.h" | 37 | #include "transport.h" |
33 | 38 | ||
34 | #define VERBOSE GNUNET_NO | 39 | #define VERBOSE GNUNET_YES |
35 | 40 | ||
36 | #define VERBOSE_ARM GNUNET_NO | 41 | #define VERBOSE_ARM GNUNET_NO |
37 | 42 | ||
38 | #define START_ARM GNUNET_YES | 43 | #define START_ARM GNUNET_YES |
39 | 44 | ||
40 | #define VERBOSE_TRANSPORT GNUNET_NO | ||
41 | |||
42 | /** | 45 | /** |
43 | * How long until we give up on transmitting the message? | 46 | * How long until we give up on transmitting the message? |
44 | */ | 47 | */ |
@@ -68,6 +71,8 @@ static int is_tcp; | |||
68 | 71 | ||
69 | static int is_udp; | 72 | static int is_udp; |
70 | 73 | ||
74 | static int is_udp_nat; | ||
75 | |||
71 | GNUNET_SCHEDULER_TaskIdentifier die_task; | 76 | GNUNET_SCHEDULER_TaskIdentifier die_task; |
72 | 77 | ||
73 | #if VERBOSE | 78 | #if VERBOSE |
@@ -231,7 +236,8 @@ exchange_hello_last (void *cls, | |||
231 | GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) | 236 | GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) |
232 | message, &me->id)); | 237 | message, &me->id)); |
233 | 238 | ||
234 | GNUNET_TRANSPORT_offer_hello (p1.th, message); | 239 | /* Can't we get away with only offering one hello? */ |
240 | /* GNUNET_TRANSPORT_offer_hello (p1.th, message); */ | ||
235 | 241 | ||
236 | /*sleep(1);*/ /* Make sure we are not falling prey to the "favorable timing" bug... */ | 242 | /*sleep(1);*/ /* Make sure we are not falling prey to the "favorable timing" bug... */ |
237 | 243 | ||
@@ -264,44 +270,6 @@ exchange_hello (void *cls, | |||
264 | GNUNET_TRANSPORT_get_hello (p2.th, &exchange_hello_last, &p2); | 270 | GNUNET_TRANSPORT_get_hello (p2.th, &exchange_hello_last, &p2); |
265 | } | 271 | } |
266 | 272 | ||
267 | #if WRITECONFIG | ||
268 | static void | ||
269 | setTransportOptions(char * filename) | ||
270 | { | ||
271 | struct GNUNET_CONFIGURATION_Handle * tempcfg; | ||
272 | |||
273 | tempcfg = GNUNET_CONFIGURATION_create(); | ||
274 | GNUNET_CONFIGURATION_load (tempcfg, filename); | ||
275 | |||
276 | unsigned long long curr_port; | ||
277 | GNUNET_CONFIGURATION_get_value_number(tempcfg, "transport", "port", &curr_port); | ||
278 | |||
279 | if (is_udp) | ||
280 | { | ||
281 | GNUNET_CONFIGURATION_set_value_string(tempcfg, "transport", "plugins", "udp"); | ||
282 | GNUNET_CONFIGURATION_set_value_number(tempcfg, "transport-udp", "PORT", curr_port + 3); | ||
283 | } | ||
284 | else if (is_tcp) | ||
285 | { | ||
286 | GNUNET_CONFIGURATION_set_value_string(tempcfg, "transport", "plugins", "tcp"); | ||
287 | GNUNET_CONFIGURATION_set_value_number(tempcfg, "transport-tcp", "port", curr_port + 3); | ||
288 | } | ||
289 | |||
290 | #if VERBOSE_TRANSPORT | ||
291 | GNUNET_CONFIGURATION_set_value_string(tempcfg, "transport", "DEBUG", "YES"); | ||
292 | GNUNET_CONFIGURATION_set_value_string(tempcfg, "transport", "PREFIX", "xterm -e xterm -T transport -e gdb --args"); | ||
293 | #else | ||
294 | GNUNET_CONFIGURATION_set_value_string(tempcfg, "transport", "DEBUG", "NO"); | ||
295 | GNUNET_CONFIGURATION_set_value_string(tempcfg, "transport", "PREFIX", ""); | ||
296 | #endif | ||
297 | |||
298 | GNUNET_CONFIGURATION_write(tempcfg, filename); | ||
299 | |||
300 | GNUNET_CONFIGURATION_destroy(tempcfg); | ||
301 | return; | ||
302 | } | ||
303 | #endif | ||
304 | |||
305 | static void | 273 | static void |
306 | run (void *cls, | 274 | run (void *cls, |
307 | struct GNUNET_SCHEDULER_Handle *s, | 275 | struct GNUNET_SCHEDULER_Handle *s, |
@@ -325,6 +293,14 @@ run (void *cls, | |||
325 | setup_peer (&p1, "test_transport_api_tcp_peer1.conf"); | 293 | setup_peer (&p1, "test_transport_api_tcp_peer1.conf"); |
326 | setup_peer (&p2, "test_transport_api_tcp_peer2.conf"); | 294 | setup_peer (&p2, "test_transport_api_tcp_peer2.conf"); |
327 | } | 295 | } |
296 | if (is_udp_nat) | ||
297 | { | ||
298 | setup_peer (&p1, "test_transport_api_udp_nat_peer1.conf"); | ||
299 | setup_peer (&p2, "test_transport_api_udp_nat_peer2.conf"); | ||
300 | } | ||
301 | |||
302 | GNUNET_assert(p1.th != NULL); | ||
303 | GNUNET_assert(p2.th != NULL); | ||
328 | 304 | ||
329 | GNUNET_TRANSPORT_get_hello (p1.th, &exchange_hello, &p1); | 305 | GNUNET_TRANSPORT_get_hello (p1.th, &exchange_hello, &p1); |
330 | } | 306 | } |
@@ -366,8 +342,14 @@ main (int argc, char *argv[]) | |||
366 | 342 | ||
367 | if (strstr(argv[0], "tcp") != NULL) | 343 | if (strstr(argv[0], "tcp") != NULL) |
368 | { | 344 | { |
345 | |||
369 | is_tcp = GNUNET_YES; | 346 | is_tcp = GNUNET_YES; |
370 | } | 347 | } |
348 | else if (strstr(argv[0], "udp_nat") != NULL) | ||
349 | { | ||
350 | fprintf(stderr, "this is a udp_nat test!\n"); | ||
351 | is_udp_nat = GNUNET_YES; | ||
352 | } | ||
371 | else if (strstr(argv[0], "udp") != NULL) | 353 | else if (strstr(argv[0], "udp") != NULL) |
372 | { | 354 | { |
373 | is_udp = GNUNET_YES; | 355 | is_udp = GNUNET_YES; |
diff --git a/src/transport/test_transport_api_udp_nat_peer1.conf b/src/transport/test_transport_api_udp_nat_peer1.conf new file mode 100644 index 000000000..56978a5d6 --- /dev/null +++ b/src/transport/test_transport_api_udp_nat_peer1.conf | |||
@@ -0,0 +1,137 @@ | |||
1 | [transport-udp-nat] | ||
2 | PORT = 12368 | ||
3 | BEHIND_NAT = NO | ||
4 | EXTERNAL_ADDRESS = 127.0.0.1 | ||
5 | STARTING_PORT = 22222 | ||
6 | |||
7 | [fs] | ||
8 | ALLOW_SHUTDOWN = YES | ||
9 | ACCEPT_FROM6 = ::1; | ||
10 | ACCEPT_FROM = 127.0.0.1; | ||
11 | BINARY = gnunet-service-fs | ||
12 | CONFIG = $DEFAULTCONFIG | ||
13 | HOME = $SERVICEHOME | ||
14 | HOSTNAME = localhost | ||
15 | PORT = 2094 | ||
16 | INDEXDB = $SERVICEHOME/idxinfo.lst | ||
17 | |||
18 | [datastore-sqlite] | ||
19 | FILENAME = $SERVICEHOME/datastore/sqlite.db | ||
20 | |||
21 | [datastore] | ||
22 | DATABASE = sqlite | ||
23 | BLOOMFILTER = $SERVICEHOME/fs/bloomfilter | ||
24 | QUOTA = 100000000 | ||
25 | ALLOW_SHUTDOWN = YES | ||
26 | ACCEPT_FROM6 = ::1; | ||
27 | ACCEPT_FROM = 127.0.0.1; | ||
28 | BINARY = gnunet-service-datastore | ||
29 | CONFIG = $DEFAULTCONFIG | ||
30 | HOME = $SERVICEHOME | ||
31 | HOSTNAME = localhost | ||
32 | PORT = 2093 | ||
33 | |||
34 | [hostlist] | ||
35 | HTTP-PROXY = | ||
36 | SERVERS = http://gnunet.org:8080/ | ||
37 | OPTIONS = -b | ||
38 | BINARY = gnunet-daemon-hostlist | ||
39 | CONFIG = $DEFAULTCONFIG | ||
40 | HOME = $SERVICEHOME | ||
41 | HOSTNAME = localhost | ||
42 | HTTPPORT = 8080 | ||
43 | |||
44 | [topology] | ||
45 | BINARY = gnunet-daemon-topology | ||
46 | CONFIG = $DEFAULTCONFIG | ||
47 | FRIENDS = $SERVICEHOME/friends | ||
48 | TARGET-CONNECTION-COUNT = 16 | ||
49 | AUTOCONNECT = YES | ||
50 | FRIENDS-ONLY = NO | ||
51 | MINIMUM-FRIENDS = 0 | ||
52 | |||
53 | [core] | ||
54 | TOTAL_QUOTA_OUT = 3932160 | ||
55 | TOTAL_QUOTA_IN = 3932160 | ||
56 | ALLOW_SHUTDOWN = YES | ||
57 | ACCEPT_FROM6 = ::1; | ||
58 | ACCEPT_FROM = 127.0.0.1; | ||
59 | BINARY = gnunet-service-core | ||
60 | CONFIG = $DEFAULTCONFIG | ||
61 | HOME = $SERVICEHOME | ||
62 | HOSTNAME = localhost | ||
63 | PORT = 2092 | ||
64 | |||
65 | [transport] | ||
66 | PLUGINS = udp_nat | ||
67 | DEBUG = YES | ||
68 | ALLOW_SHUTDOWN = YES | ||
69 | ACCEPT_FROM6 = ::1; | ||
70 | ACCEPT_FROM = 127.0.0.1; | ||
71 | NEIGHBOUR_LIMIT = 50 | ||
72 | BINARY = /home/mrwiggles/documents/research/gnunet/gnunet-ng/src/transport/.libs/gnunet-service-transport | ||
73 | CONFIG = $DEFAULTCONFIG | ||
74 | HOME = $SERVICEHOME | ||
75 | HOSTNAME = localhost | ||
76 | PORT = 12365 | ||
77 | #PREFIX = valgrind --track-origins=yes --leak-check=full --log-file=valgrind_udp_peer1.log | ||
78 | PREFIX = xterm -e xterm -T transport -e gdb --args | ||
79 | |||
80 | [peerinfo] | ||
81 | TRUST = $SERVICEHOME/data/credit/ | ||
82 | HOSTS = $SERVICEHOME/data/hosts/ | ||
83 | ALLOW_SHUTDOWN = YES | ||
84 | ACCEPT_FROM6 = ::1; | ||
85 | ACCEPT_FROM = 127.0.0.1; | ||
86 | BINARY = gnunet-service-peerinfo | ||
87 | CONFIG = $DEFAULTCONFIG | ||
88 | HOME = $SERVICEHOME | ||
89 | HOSTNAME = localhost | ||
90 | PORT = 12369 | ||
91 | |||
92 | [resolver] | ||
93 | ALLOW_SHUTDOWN = YES | ||
94 | ACCEPT_FROM6 = ::1; | ||
95 | ACCEPT_FROM = 127.0.0.1; | ||
96 | BINARY = gnunet-service-resolver | ||
97 | CONFIG = $DEFAULTCONFIG | ||
98 | HOME = $SERVICEHOME | ||
99 | HOSTNAME = localhost | ||
100 | PORT = 12364 | ||
101 | |||
102 | [statistics] | ||
103 | ALLOW_SHUTDOWN = YES | ||
104 | ACCEPT_FROM6 = ::1; | ||
105 | ACCEPT_FROM = 127.0.0.1; | ||
106 | BINARY = gnunet-service-statistics | ||
107 | CONFIG = $DEFAULTCONFIG | ||
108 | HOME = $SERVICEHOME | ||
109 | HOSTNAME = localhost | ||
110 | PORT = 12367 | ||
111 | |||
112 | [arm] | ||
113 | DEFAULTSERVICES = | ||
114 | ALLOW_SHUTDOWN = YES | ||
115 | ACCEPT_FROM6 = ::1; | ||
116 | ACCEPT_FROM = 127.0.0.1; | ||
117 | BINARY = gnunet-service-arm | ||
118 | CONFIG = $DEFAULTCONFIG | ||
119 | HOME = $SERVICEHOME | ||
120 | HOSTNAME = localhost | ||
121 | PORT = 12366 | ||
122 | |||
123 | [transport-tcp] | ||
124 | ALLOW_SHUTDOWN = NO | ||
125 | TIMEOUT = 300000 | ||
126 | PORT = 12368 | ||
127 | |||
128 | [TESTING] | ||
129 | WEAKRANDOM = YES | ||
130 | |||
131 | [gnunetd] | ||
132 | HOSTKEY = $SERVICEHOME/.hostkey | ||
133 | |||
134 | [PATHS] | ||
135 | DEFAULTCONFIG = test_transport_api_udp_nat_peer1.conf | ||
136 | SERVICEHOME = /tmp/test-gnunetd-transport-peer-1/ | ||
137 | |||
diff --git a/src/transport/test_transport_api_udp_nat_peer2.conf b/src/transport/test_transport_api_udp_nat_peer2.conf new file mode 100644 index 000000000..d0dbe9653 --- /dev/null +++ b/src/transport/test_transport_api_udp_nat_peer2.conf | |||
@@ -0,0 +1,137 @@ | |||
1 | [transport-udp-nat] | ||
2 | PORT = 22368 | ||
3 | BEHIND_NAT = YES | ||
4 | EXTERNAL_ADDRESS = 127.0.0.1 | ||
5 | STARTING_PORT = 22222 | ||
6 | |||
7 | [fs] | ||
8 | ALLOW_SHUTDOWN = YES | ||
9 | ACCEPT_FROM6 = ::1; | ||
10 | ACCEPT_FROM = 127.0.0.1; | ||
11 | BINARY = gnunet-service-fs | ||
12 | CONFIG = $DEFAULTCONFIG | ||
13 | HOME = $SERVICEHOME | ||
14 | HOSTNAME = localhost | ||
15 | PORT = 2094 | ||
16 | INDEXDB = $SERVICEHOME/idxinfo.lst | ||
17 | |||
18 | [datastore-sqlite] | ||
19 | FILENAME = $SERVICEHOME/datastore/sqlite.db | ||
20 | |||
21 | [datastore] | ||
22 | DATABASE = sqlite | ||
23 | BLOOMFILTER = $SERVICEHOME/fs/bloomfilter | ||
24 | QUOTA = 100000000 | ||
25 | ALLOW_SHUTDOWN = YES | ||
26 | ACCEPT_FROM6 = ::1; | ||
27 | ACCEPT_FROM = 127.0.0.1; | ||
28 | BINARY = gnunet-service-datastore | ||
29 | CONFIG = $DEFAULTCONFIG | ||
30 | HOME = $SERVICEHOME | ||
31 | HOSTNAME = localhost | ||
32 | PORT = 2093 | ||
33 | |||
34 | [hostlist] | ||
35 | HTTP-PROXY = | ||
36 | SERVERS = http://gnunet.org:8080/ | ||
37 | OPTIONS = -b | ||
38 | BINARY = gnunet-daemon-hostlist | ||
39 | CONFIG = $DEFAULTCONFIG | ||
40 | HOME = $SERVICEHOME | ||
41 | HOSTNAME = localhost | ||
42 | HTTPPORT = 8080 | ||
43 | |||
44 | [topology] | ||
45 | BINARY = gnunet-daemon-topology | ||
46 | CONFIG = $DEFAULTCONFIG | ||
47 | FRIENDS = $SERVICEHOME/friends | ||
48 | TARGET-CONNECTION-COUNT = 16 | ||
49 | AUTOCONNECT = YES | ||
50 | FRIENDS-ONLY = NO | ||
51 | MINIMUM-FRIENDS = 0 | ||
52 | |||
53 | [core] | ||
54 | TOTAL_QUOTA_OUT = 3932160 | ||
55 | TOTAL_QUOTA_IN = 3932160 | ||
56 | ALLOW_SHUTDOWN = YES | ||
57 | ACCEPT_FROM6 = ::1; | ||
58 | ACCEPT_FROM = 127.0.0.1; | ||
59 | BINARY = gnunet-service-core | ||
60 | CONFIG = $DEFAULTCONFIG | ||
61 | HOME = $SERVICEHOME | ||
62 | HOSTNAME = localhost | ||
63 | PORT = 2092 | ||
64 | |||
65 | [transport] | ||
66 | PLUGINS = udp_nat | ||
67 | DEBUG = YES | ||
68 | PREFIX = | ||
69 | ALLOW_SHUTDOWN = YES | ||
70 | ACCEPT_FROM6 = ::1; | ||
71 | ACCEPT_FROM = 127.0.0.1; | ||
72 | NEIGHBOUR_LIMIT = 50 | ||
73 | BINARY = /home/mrwiggles/documents/research/gnunet/gnunet-ng/src/transport/.libs/gnunet-service-transport | ||
74 | CONFIG = $DEFAULTCONFIG | ||
75 | HOME = $SERVICEHOME | ||
76 | HOSTNAME = localhost | ||
77 | PORT = 22365 | ||
78 | PREFIX = xterm -e xterm -T transport -e gdb --args | ||
79 | |||
80 | [peerinfo] | ||
81 | TRUST = $SERVICEHOME/data/credit/ | ||
82 | HOSTS = $SERVICEHOME/data/hosts/ | ||
83 | ALLOW_SHUTDOWN = YES | ||
84 | ACCEPT_FROM6 = ::1; | ||
85 | ACCEPT_FROM = 127.0.0.1; | ||
86 | BINARY = gnunet-service-peerinfo | ||
87 | CONFIG = $DEFAULTCONFIG | ||
88 | HOME = $SERVICEHOME | ||
89 | HOSTNAME = localhost | ||
90 | PORT = 22369 | ||
91 | |||
92 | [resolver] | ||
93 | ALLOW_SHUTDOWN = YES | ||
94 | ACCEPT_FROM6 = ::1; | ||
95 | ACCEPT_FROM = 127.0.0.1; | ||
96 | BINARY = gnunet-service-resolver | ||
97 | CONFIG = $DEFAULTCONFIG | ||
98 | HOME = $SERVICEHOME | ||
99 | HOSTNAME = localhost | ||
100 | PORT = 22364 | ||
101 | |||
102 | [statistics] | ||
103 | ALLOW_SHUTDOWN = YES | ||
104 | ACCEPT_FROM6 = ::1; | ||
105 | ACCEPT_FROM = 127.0.0.1; | ||
106 | BINARY = gnunet-service-statistics | ||
107 | CONFIG = $DEFAULTCONFIG | ||
108 | HOME = $SERVICEHOME | ||
109 | HOSTNAME = localhost | ||
110 | PORT = 22367 | ||
111 | |||
112 | [arm] | ||
113 | DEFAULTSERVICES = | ||
114 | ALLOW_SHUTDOWN = YES | ||
115 | ACCEPT_FROM6 = ::1; | ||
116 | ACCEPT_FROM = 127.0.0.1; | ||
117 | BINARY = gnunet-service-arm | ||
118 | CONFIG = $DEFAULTCONFIG | ||
119 | HOME = $SERVICEHOME | ||
120 | HOSTNAME = localhost | ||
121 | PORT = 22366 | ||
122 | |||
123 | [transport-tcp] | ||
124 | ALLOW_SHUTDOWN = NO | ||
125 | TIMEOUT = 300000 | ||
126 | PORT = 22368 | ||
127 | |||
128 | [TESTING] | ||
129 | WEAKRANDOM = YES | ||
130 | |||
131 | [gnunetd] | ||
132 | HOSTKEY = $SERVICEHOME/.hostkey | ||
133 | |||
134 | [PATHS] | ||
135 | DEFAULTCONFIG = test_transport_api_udp_nat_peer2.conf | ||
136 | SERVICEHOME = /tmp/test-gnunetd-transport-peer-2/ | ||
137 | |||