aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNathan S. Evans <evans@in.tum.de>2010-02-19 13:33:17 +0000
committerNathan S. Evans <evans@in.tum.de>2010-02-19 13:33:17 +0000
commite1fe5a5ca9711cb615e4c85daf002364592814b9 (patch)
tree7aee3d55a6c64bbe2171bb2eebd001e057606ee6 /src
parent6a1a0c383228cff1b85480e4094c66b92a1be9ce (diff)
downloadgnunet-e1fe5a5ca9711cb615e4c85daf002364592814b9.tar.gz
gnunet-e1fe5a5ca9711cb615e4c85daf002364592814b9.zip
semi functional nat punchy dealy
Diffstat (limited to 'src')
-rw-r--r--src/transport/plugin_transport_udp_nat.c1627
-rw-r--r--src/transport/test_transport_api.c68
-rw-r--r--src/transport/test_transport_api_udp_nat_peer1.conf137
-rw-r--r--src/transport/test_transport_api_udp_nat_peer2.conf137
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 */
67static 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 */
89struct 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 */
107struct 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 */
119struct 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 */
132struct UDP_NAT_ProbeMessageConfirmation
133{
134 /**
135 * Message header
136 */
137 struct GNUNET_MessageHeader header;
138
139};
140
141
142
143/* Forward definition */
144struct Plugin;
145
146struct PrettyPrinterContext
147{
148 GNUNET_TRANSPORT_AddressStringCallback asc;
149 void *asc_cls;
150 uint16_t port;
151};
152
153struct 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 */
195struct 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
244struct 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 */
288struct 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 */
384static struct GNUNET_NETWORK_Handle *udp_nat_socks[UDP_NAT_LISTEN_PORTS];
385
386
387/**
388 * Forward declaration.
389 */
390void
391udp_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 */
400void
401udp_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 */
410static int
411udp_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
447struct PeerSession *
448find_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 */
486static ssize_t
487udp_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 */
558void
559run_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 */
614static ssize_t
615udp_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 */
707static int
708process_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 */
766static void
767process_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 */
788static void
789send_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
819void
820dummy_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 */
831void
832udp_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 */
864struct UDP_NAT_Probes *
865find_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 */
887static void
888udp_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 */
949static void
950udp_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 */
1095static void
1096udp_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 */
1198static int
1199udp_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 */
1336static uint16_t
1337check_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 */
1367static int
1368udp_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 */
1410static void
1411append_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 */
1442static void
1443udp_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 */
1496static void
1497udp_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 */
1508void *
1509libgnunet_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
1607void *
1608libgnunet_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
69static int is_udp; 72static int is_udp;
70 73
74static int is_udp_nat;
75
71GNUNET_SCHEDULER_TaskIdentifier die_task; 76GNUNET_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
268static void
269setTransportOptions(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
305static void 273static void
306run (void *cls, 274run (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]
2PORT = 12368
3BEHIND_NAT = NO
4EXTERNAL_ADDRESS = 127.0.0.1
5STARTING_PORT = 22222
6
7[fs]
8ALLOW_SHUTDOWN = YES
9ACCEPT_FROM6 = ::1;
10ACCEPT_FROM = 127.0.0.1;
11BINARY = gnunet-service-fs
12CONFIG = $DEFAULTCONFIG
13HOME = $SERVICEHOME
14HOSTNAME = localhost
15PORT = 2094
16INDEXDB = $SERVICEHOME/idxinfo.lst
17
18[datastore-sqlite]
19FILENAME = $SERVICEHOME/datastore/sqlite.db
20
21[datastore]
22DATABASE = sqlite
23BLOOMFILTER = $SERVICEHOME/fs/bloomfilter
24QUOTA = 100000000
25ALLOW_SHUTDOWN = YES
26ACCEPT_FROM6 = ::1;
27ACCEPT_FROM = 127.0.0.1;
28BINARY = gnunet-service-datastore
29CONFIG = $DEFAULTCONFIG
30HOME = $SERVICEHOME
31HOSTNAME = localhost
32PORT = 2093
33
34[hostlist]
35HTTP-PROXY =
36SERVERS = http://gnunet.org:8080/
37OPTIONS = -b
38BINARY = gnunet-daemon-hostlist
39CONFIG = $DEFAULTCONFIG
40HOME = $SERVICEHOME
41HOSTNAME = localhost
42HTTPPORT = 8080
43
44[topology]
45BINARY = gnunet-daemon-topology
46CONFIG = $DEFAULTCONFIG
47FRIENDS = $SERVICEHOME/friends
48TARGET-CONNECTION-COUNT = 16
49AUTOCONNECT = YES
50FRIENDS-ONLY = NO
51MINIMUM-FRIENDS = 0
52
53[core]
54TOTAL_QUOTA_OUT = 3932160
55TOTAL_QUOTA_IN = 3932160
56ALLOW_SHUTDOWN = YES
57ACCEPT_FROM6 = ::1;
58ACCEPT_FROM = 127.0.0.1;
59BINARY = gnunet-service-core
60CONFIG = $DEFAULTCONFIG
61HOME = $SERVICEHOME
62HOSTNAME = localhost
63PORT = 2092
64
65[transport]
66PLUGINS = udp_nat
67DEBUG = YES
68ALLOW_SHUTDOWN = YES
69ACCEPT_FROM6 = ::1;
70ACCEPT_FROM = 127.0.0.1;
71NEIGHBOUR_LIMIT = 50
72BINARY = /home/mrwiggles/documents/research/gnunet/gnunet-ng/src/transport/.libs/gnunet-service-transport
73CONFIG = $DEFAULTCONFIG
74HOME = $SERVICEHOME
75HOSTNAME = localhost
76PORT = 12365
77#PREFIX = valgrind --track-origins=yes --leak-check=full --log-file=valgrind_udp_peer1.log
78PREFIX = xterm -e xterm -T transport -e gdb --args
79
80[peerinfo]
81TRUST = $SERVICEHOME/data/credit/
82HOSTS = $SERVICEHOME/data/hosts/
83ALLOW_SHUTDOWN = YES
84ACCEPT_FROM6 = ::1;
85ACCEPT_FROM = 127.0.0.1;
86BINARY = gnunet-service-peerinfo
87CONFIG = $DEFAULTCONFIG
88HOME = $SERVICEHOME
89HOSTNAME = localhost
90PORT = 12369
91
92[resolver]
93ALLOW_SHUTDOWN = YES
94ACCEPT_FROM6 = ::1;
95ACCEPT_FROM = 127.0.0.1;
96BINARY = gnunet-service-resolver
97CONFIG = $DEFAULTCONFIG
98HOME = $SERVICEHOME
99HOSTNAME = localhost
100PORT = 12364
101
102[statistics]
103ALLOW_SHUTDOWN = YES
104ACCEPT_FROM6 = ::1;
105ACCEPT_FROM = 127.0.0.1;
106BINARY = gnunet-service-statistics
107CONFIG = $DEFAULTCONFIG
108HOME = $SERVICEHOME
109HOSTNAME = localhost
110PORT = 12367
111
112[arm]
113DEFAULTSERVICES =
114ALLOW_SHUTDOWN = YES
115ACCEPT_FROM6 = ::1;
116ACCEPT_FROM = 127.0.0.1;
117BINARY = gnunet-service-arm
118CONFIG = $DEFAULTCONFIG
119HOME = $SERVICEHOME
120HOSTNAME = localhost
121PORT = 12366
122
123[transport-tcp]
124ALLOW_SHUTDOWN = NO
125TIMEOUT = 300000
126PORT = 12368
127
128[TESTING]
129WEAKRANDOM = YES
130
131[gnunetd]
132HOSTKEY = $SERVICEHOME/.hostkey
133
134[PATHS]
135DEFAULTCONFIG = test_transport_api_udp_nat_peer1.conf
136SERVICEHOME = /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]
2PORT = 22368
3BEHIND_NAT = YES
4EXTERNAL_ADDRESS = 127.0.0.1
5STARTING_PORT = 22222
6
7[fs]
8ALLOW_SHUTDOWN = YES
9ACCEPT_FROM6 = ::1;
10ACCEPT_FROM = 127.0.0.1;
11BINARY = gnunet-service-fs
12CONFIG = $DEFAULTCONFIG
13HOME = $SERVICEHOME
14HOSTNAME = localhost
15PORT = 2094
16INDEXDB = $SERVICEHOME/idxinfo.lst
17
18[datastore-sqlite]
19FILENAME = $SERVICEHOME/datastore/sqlite.db
20
21[datastore]
22DATABASE = sqlite
23BLOOMFILTER = $SERVICEHOME/fs/bloomfilter
24QUOTA = 100000000
25ALLOW_SHUTDOWN = YES
26ACCEPT_FROM6 = ::1;
27ACCEPT_FROM = 127.0.0.1;
28BINARY = gnunet-service-datastore
29CONFIG = $DEFAULTCONFIG
30HOME = $SERVICEHOME
31HOSTNAME = localhost
32PORT = 2093
33
34[hostlist]
35HTTP-PROXY =
36SERVERS = http://gnunet.org:8080/
37OPTIONS = -b
38BINARY = gnunet-daemon-hostlist
39CONFIG = $DEFAULTCONFIG
40HOME = $SERVICEHOME
41HOSTNAME = localhost
42HTTPPORT = 8080
43
44[topology]
45BINARY = gnunet-daemon-topology
46CONFIG = $DEFAULTCONFIG
47FRIENDS = $SERVICEHOME/friends
48TARGET-CONNECTION-COUNT = 16
49AUTOCONNECT = YES
50FRIENDS-ONLY = NO
51MINIMUM-FRIENDS = 0
52
53[core]
54TOTAL_QUOTA_OUT = 3932160
55TOTAL_QUOTA_IN = 3932160
56ALLOW_SHUTDOWN = YES
57ACCEPT_FROM6 = ::1;
58ACCEPT_FROM = 127.0.0.1;
59BINARY = gnunet-service-core
60CONFIG = $DEFAULTCONFIG
61HOME = $SERVICEHOME
62HOSTNAME = localhost
63PORT = 2092
64
65[transport]
66PLUGINS = udp_nat
67DEBUG = YES
68PREFIX =
69ALLOW_SHUTDOWN = YES
70ACCEPT_FROM6 = ::1;
71ACCEPT_FROM = 127.0.0.1;
72NEIGHBOUR_LIMIT = 50
73BINARY = /home/mrwiggles/documents/research/gnunet/gnunet-ng/src/transport/.libs/gnunet-service-transport
74CONFIG = $DEFAULTCONFIG
75HOME = $SERVICEHOME
76HOSTNAME = localhost
77PORT = 22365
78PREFIX = xterm -e xterm -T transport -e gdb --args
79
80[peerinfo]
81TRUST = $SERVICEHOME/data/credit/
82HOSTS = $SERVICEHOME/data/hosts/
83ALLOW_SHUTDOWN = YES
84ACCEPT_FROM6 = ::1;
85ACCEPT_FROM = 127.0.0.1;
86BINARY = gnunet-service-peerinfo
87CONFIG = $DEFAULTCONFIG
88HOME = $SERVICEHOME
89HOSTNAME = localhost
90PORT = 22369
91
92[resolver]
93ALLOW_SHUTDOWN = YES
94ACCEPT_FROM6 = ::1;
95ACCEPT_FROM = 127.0.0.1;
96BINARY = gnunet-service-resolver
97CONFIG = $DEFAULTCONFIG
98HOME = $SERVICEHOME
99HOSTNAME = localhost
100PORT = 22364
101
102[statistics]
103ALLOW_SHUTDOWN = YES
104ACCEPT_FROM6 = ::1;
105ACCEPT_FROM = 127.0.0.1;
106BINARY = gnunet-service-statistics
107CONFIG = $DEFAULTCONFIG
108HOME = $SERVICEHOME
109HOSTNAME = localhost
110PORT = 22367
111
112[arm]
113DEFAULTSERVICES =
114ALLOW_SHUTDOWN = YES
115ACCEPT_FROM6 = ::1;
116ACCEPT_FROM = 127.0.0.1;
117BINARY = gnunet-service-arm
118CONFIG = $DEFAULTCONFIG
119HOME = $SERVICEHOME
120HOSTNAME = localhost
121PORT = 22366
122
123[transport-tcp]
124ALLOW_SHUTDOWN = NO
125TIMEOUT = 300000
126PORT = 22368
127
128[TESTING]
129WEAKRANDOM = YES
130
131[gnunetd]
132HOSTKEY = $SERVICEHOME/.hostkey
133
134[PATHS]
135DEFAULTCONFIG = test_transport_api_udp_nat_peer2.conf
136SERVICEHOME = /tmp/test-gnunetd-transport-peer-2/
137