e5e741df399b54be1f40a4faf9be8d9812bb78c8
[oweals/gnunet.git] / src / transport / plugin_transport_udp.c
1 /*
2      This file is part of GNUnet
3      (C) 2010 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file 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 is behind a NAT.  This is based on pwnat (http://samy.pl/pwnat)
30  * created by Samy Kamkar.  When configured with the PWNAT options, this
31  * transport will start a server daemon which sends dummy ICMP and UDP
32  * messages out to a predefined address (typically 1.2.3.4).
33  *
34  * When a non-NAT'd peer (the client) learns of the NAT'd peer (the server)
35  * address, it will send ICMP RESPONSES to the NAT'd peers external address.
36  * The NAT box should forward these faked responses to the server, which
37  * can then connect directly to the non-NAT'd peer.
38  */
39
40 #include "platform.h"
41 #include "gnunet_hello_lib.h"
42 #include "gnunet_connection_lib.h"
43 #include "gnunet_container_lib.h"
44 #include "gnunet_nat_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_signatures.h"
51 #include "gnunet_statistics_service.h"
52 #include "gnunet_transport_service.h"
53 #include "gnunet_transport_plugin.h"
54 #include "transport.h"
55
56 #define DEBUG_UDP GNUNET_NO
57
58 #define MAX_PROBES 20
59
60 /*
61  * Transport cost to peer, always 1 for UDP (direct connection)
62  */
63 #define UDP_DIRECT_DISTANCE 1
64
65 #define DEFAULT_NAT_PORT 0
66
67 /**
68  * How long until we give up on transmitting the welcome message?
69  */
70 #define HOSTNAME_RESOLVE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
71
72 /**
73  * Starting port for listening and sending, eventually a config value
74  */
75 #define UDP_NAT_DEFAULT_PORT 22086
76
77 /**
78  * UDP Message-Packet header.
79  */
80 struct UDPMessage
81 {
82   /**
83    * Message header.
84    */
85   struct GNUNET_MessageHeader header;
86
87   /**
88    * What is the identity of the sender (GNUNET_hash of public key)
89    */
90   struct GNUNET_PeerIdentity sender;
91
92 };
93
94 /**
95  * Network format for IPv4 addresses.
96  */
97 struct IPv4UdpAddress
98 {
99   /**
100    * IPv4 address, in network byte order.
101    */
102   uint32_t ipv4_addr GNUNET_PACKED;
103
104   /**
105    * Port number, in network byte order.
106    */
107   uint16_t u4_port GNUNET_PACKED;
108 };
109
110
111 /**
112  * Network format for IPv6 addresses.
113  */
114 struct IPv6UdpAddress
115 {
116   /**
117    * IPv6 address.
118    */
119   struct in6_addr ipv6_addr GNUNET_PACKED;
120
121   /**
122    * Port number, in network byte order.
123    */
124   uint16_t u6_port GNUNET_PACKED;
125 };
126
127 /* Forward definition */
128 struct Plugin;
129
130 struct PrettyPrinterContext
131 {
132   GNUNET_TRANSPORT_AddressStringCallback asc;
133   void *asc_cls;
134   uint16_t port;
135 };
136
137 struct MessageQueue
138 {
139   /**
140    * Linked List
141    */
142   struct MessageQueue *next;
143
144   /**
145    * Session this message belongs to
146    */
147   struct PeerSession *session;
148
149   /**
150    * Actual message to be sent
151    */
152   char *msgbuf;
153
154   /**
155    * Size of message buffer to be sent
156    */
157   size_t msgbuf_size;
158
159   /**
160    * When to discard this message
161    */
162   struct GNUNET_TIME_Absolute timeout;
163
164   /**
165    * Continuation to call when this message goes out
166    */
167   GNUNET_TRANSPORT_TransmitContinuation cont;
168
169   /**
170    * closure for continuation
171    */
172   void *cont_cls;
173
174 };
175
176 /**
177  * UDP NAT Probe message definition
178  */
179 struct UDP_NAT_ProbeMessage
180 {
181   /**
182    * Message header
183    */
184   struct GNUNET_MessageHeader header;
185
186 };
187
188 /**
189  * UDP NAT Probe message reply definition
190  */
191 struct UDP_NAT_ProbeMessageReply
192 {
193   /**
194    * Message header
195    */
196   struct GNUNET_MessageHeader header;
197
198 };
199
200
201 /**
202  * UDP NAT Probe message confirm definition
203  */
204 struct UDP_NAT_ProbeMessageConfirmation
205 {
206   /**
207    * Message header
208    */
209   struct GNUNET_MessageHeader header;
210
211 };
212
213
214 /**
215  * UDP NAT "Session"
216  */
217 struct PeerSession
218 {
219
220   /**
221    * Stored in a linked list.
222    */
223   struct PeerSession *next;
224
225   /**
226    * Pointer to the global plugin struct.
227    */
228   struct Plugin *plugin;
229
230   /**
231    * To whom are we talking to (set to our identity
232    * if we are still waiting for the welcome message)
233    */
234   struct GNUNET_PeerIdentity target;
235
236   /**
237    * Address of the other peer (either based on our 'connect'
238    * call or on our 'accept' call).
239    */
240   void *connect_addr;
241
242   /**
243    * Length of connect_addr.
244    */
245   size_t connect_alen;
246
247   /**
248    * Are we still expecting the welcome message? (GNUNET_YES/GNUNET_NO)
249    */
250   int expecting_welcome;
251
252   /**
253    * From which socket do we need to send to this peer?
254    */
255   struct GNUNET_NETWORK_Handle *sock;
256
257   /*
258    * Queue of messages for this peer, in the case that
259    * we have to await a connection...
260    */
261   struct MessageQueue *messages;
262
263 };
264
265 struct UDP_NAT_Probes
266 {
267
268   /**
269    * Linked list
270    */
271   struct UDP_NAT_Probes *next;
272
273   /**
274    * Timeout for this set of probes
275    */
276   struct GNUNET_TIME_Absolute timeout;
277
278   /**
279    * Count of how many probes we've attempted
280    */
281   int count;
282
283   /**
284    * The plugin this probe belongs to
285    */
286   struct Plugin *plugin;
287
288   /**
289    * The task used to send these probes
290    */
291   GNUNET_SCHEDULER_TaskIdentifier task;
292
293   /**
294    * Network address (always ipv4!)
295    */
296   struct IPv4UdpAddress addr;
297
298 };
299
300
301 /**
302  * Information we keep for each of our listen sockets.
303  */
304 struct UDP_Sock_Info
305 {
306   /**
307    * The network handle
308    */
309   struct GNUNET_NETWORK_Handle *desc;
310
311   /**
312    * The port we bound to
313    */
314   uint16_t port;
315 };
316
317
318 /**
319  * Encapsulation of all of the state of the plugin.
320  */
321 struct Plugin
322 {
323   /**
324    * Our environment.
325    */
326   struct GNUNET_TRANSPORT_PluginEnvironment *env;
327
328   /*
329    * Session of peers with whom we are currently connected
330    */
331   struct PeerSession *sessions;
332
333   /**
334    * ID of select task
335    */
336   GNUNET_SCHEDULER_TaskIdentifier select_task;
337
338   /**
339    * Port to listen on.
340    */
341   uint16_t port;
342
343   /**
344    * Address we were told to bind to exclusively (IPv4).
345    */
346   char *bind_address;
347
348   /**
349    * Address we were told to bind to exclusively (IPv6).
350    */
351   char *bind6_address;
352
353   /**
354    * Handle to NAT traversal support.
355    */
356   struct GNUNET_NAT_Handle *nat;
357
358   /**
359    * FD Read set
360    */
361   struct GNUNET_NETWORK_FDSet *rs;
362
363   /**
364    * Probes in flight
365    */
366   struct UDP_NAT_Probes *probes;
367
368   /**
369    * socket that we transmit all IPv4 data with
370    */
371   struct UDP_Sock_Info udp_sockv4;
372
373   /**
374    * socket that we transmit all IPv6 data with
375    */
376   struct UDP_Sock_Info udp_sockv6;
377
378 };
379
380
381 /**
382  * Forward declaration.
383  */
384 static void
385 udp_probe_continuation (void *cls, const struct GNUNET_PeerIdentity *target, int result);
386
387
388 /**
389  * Disconnect from a remote node.  Clean up session if we have one for this peer
390  *
391  * @param cls closure for this call (should be handle to Plugin)
392  * @param target the peeridentity of the peer to disconnect
393  * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
394  */
395 static void
396 udp_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
397 {
398   /** TODO: Implement! */
399   return;
400 }
401
402
403 struct PeerSession *
404 find_session (struct Plugin *plugin,
405               const struct GNUNET_PeerIdentity *peer)
406 {
407   struct PeerSession *pos;
408
409   pos = plugin->sessions;
410   while (pos != NULL)
411     {
412       if (memcmp(&pos->target, peer, sizeof(struct GNUNET_PeerIdentity)) == 0)
413         return pos;
414       pos = pos->next;
415     }
416
417   return pos;
418 }
419
420
421 /**
422  * Actually send out the message, assume we've got the address and
423  * send_handle squared away!
424  *
425  * @param cls closure
426  * @param send_handle which handle to send message on
427  * @param target who should receive this message (ignored by UDP)
428  * @param msgbuf one or more GNUNET_MessageHeader(s) strung together
429  * @param msgbuf_size the size of the msgbuf to send
430  * @param priority how important is the message (ignored by UDP)
431  * @param timeout when should we time out (give up) if we can not transmit?
432  * @param addr the addr to send the message to, needs to be a sockaddr for us
433  * @param addrlen the len of addr
434  * @param cont continuation to call once the message has
435  *        been transmitted (or if the transport is ready
436  *        for the next transmission call; or if the
437  *        peer disconnected...)
438  * @param cont_cls closure for cont
439  * @return the number of bytes written
440  */
441 static ssize_t
442 udp_real_send (void *cls,
443                struct GNUNET_NETWORK_Handle *send_handle,
444                const struct GNUNET_PeerIdentity *target,
445                const char *msgbuf,
446                size_t msgbuf_size,
447                unsigned int priority,
448                struct GNUNET_TIME_Relative timeout,
449                const void *addr,
450                size_t addrlen,
451                GNUNET_TRANSPORT_TransmitContinuation cont,
452                void *cont_cls)
453 {
454   struct Plugin *plugin = cls;
455   struct UDPMessage *message;
456   int ssize;
457   ssize_t sent;
458   struct sockaddr_in a4;
459   struct sockaddr_in6 a6;
460   const struct IPv4UdpAddress *t4;
461   const struct IPv6UdpAddress *t6;
462   const void *sb;
463   size_t sbs;
464
465   if (send_handle == NULL)
466     {
467       /* failed to open send socket for AF */
468       if (cont != NULL)
469         cont (cont_cls, target, GNUNET_SYSERR);
470       return 0;
471     }
472   if ((addr == NULL) || (addrlen == 0))
473     {
474 #if DEBUG_UDP
475       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
476                        "udp_real_send called without address, returning!\n");
477 #endif
478       if (cont != NULL)
479         cont (cont_cls, target, GNUNET_SYSERR);
480       return 0; /* Can never send if we don't have an address!! */
481     }
482
483   /* Build the message to be sent */
484   message = GNUNET_malloc (sizeof (struct UDPMessage) + msgbuf_size);
485   ssize = sizeof (struct UDPMessage) + msgbuf_size;
486
487   message->header.size = htons (ssize);
488   message->header.type = htons (0);
489   memcpy (&message->sender, plugin->env->my_identity,
490           sizeof (struct GNUNET_PeerIdentity));
491   memcpy (&message[1], msgbuf, msgbuf_size);
492
493   if (addrlen == sizeof (struct IPv6UdpAddress))
494     {
495       t6 = addr;
496       memset (&a6, 0, sizeof (a6));
497 #if HAVE_SOCKADDR_IN_SIN_LEN
498       a6.sin6_len = sizeof (a6);
499 #endif
500       a6.sin6_family = AF_INET6;
501       a6.sin6_port = t6->u6_port;
502       memcpy (&a6.sin6_addr,
503               &t6->ipv6_addr,
504               sizeof (struct in6_addr));
505       sb = &a6;
506       sbs = sizeof (a6);
507     }
508   else if (addrlen == sizeof (struct IPv4UdpAddress))
509     {
510       t4 = addr;
511       memset (&a4, 0, sizeof (a4));
512 #if HAVE_SOCKADDR_IN_SIN_LEN
513       a4.sin_len = sizeof (a4);
514 #endif
515       a4.sin_family = AF_INET;
516       a4.sin_port = t4->u4_port;
517       a4.sin_addr.s_addr = t4->ipv4_addr;
518       sb = &a4;
519       sbs = sizeof (a4);
520     }
521   else
522     {
523       GNUNET_break_op (0);
524       GNUNET_free (message);
525       return -1;
526     }
527
528   /* Actually send the message */
529   sent =
530     GNUNET_NETWORK_socket_sendto (send_handle, message, ssize,
531                                   sb,
532                                   sbs);
533   if (GNUNET_SYSERR == sent)
534     GNUNET_log_strerror(GNUNET_ERROR_TYPE_DEBUG, "sendto");
535   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
536               "UDP transmit %u-byte message to %s (%d: %s)\n",
537               (unsigned int) ssize,
538               GNUNET_a2s (sb, sbs),
539               (int) sent,
540               (sent < 0) ? STRERROR (errno) : "ok");
541   if (cont != NULL)
542     {
543       if (sent == GNUNET_SYSERR)
544         cont (cont_cls, target, GNUNET_SYSERR);
545       else
546         {
547           cont (cont_cls, target, GNUNET_OK);
548         }
549     }
550
551   GNUNET_free (message);
552   return sent;
553 }
554
555
556 /**
557  * Function that can be used by the transport service to transmit
558  * a message using the plugin.
559  *
560  * @param cls closure
561  * @param target who should receive this message (ignored by UDP)
562  * @param msgbuf one or more GNUNET_MessageHeader(s) strung together
563  * @param msgbuf_size the size of the msgbuf to send
564  * @param priority how important is the message (ignored by UDP)
565  * @param timeout when should we time out (give up) if we can not transmit?
566  * @param session identifier used for this session (can be NULL)
567  * @param addr the addr to send the message to, needs to be a sockaddr for us
568  * @param addrlen the len of addr
569  * @param force_address not used, we had better have an address to send to
570  *        because we are stateless!!
571  * @param cont continuation to call once the message has
572  *        been transmitted (or if the transport is ready
573  *        for the next transmission call; or if the
574  *        peer disconnected...)
575  * @param cont_cls closure for cont
576  *
577  * @return the number of bytes written (may return 0 and the message can
578  *         still be transmitted later!)
579  */
580 static ssize_t
581 udp_plugin_send (void *cls,
582                      const struct GNUNET_PeerIdentity *target,
583                      const char *msgbuf,
584                      size_t msgbuf_size,
585                      unsigned int priority,
586                      struct GNUNET_TIME_Relative timeout,
587                      struct Session *session,
588                      const void *addr,
589                      size_t addrlen,
590                      int force_address,
591                      GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
592 {
593   struct Plugin *plugin = cls;
594   ssize_t sent;
595   struct MessageQueue *temp_message;
596   struct PeerSession *peer_session;
597   int other_peer_natd;
598   const struct IPv4UdpAddress *t4;
599   struct sockaddr_in sin4;
600
601   if (force_address == GNUNET_SYSERR)
602     return GNUNET_SYSERR;
603   GNUNET_assert (NULL == session);
604
605   other_peer_natd = GNUNET_NO;
606   if (addrlen == sizeof(struct IPv4UdpAddress))
607     {
608       t4 = addr;
609       if (ntohs(t4->u4_port) == 0)
610         other_peer_natd = GNUNET_YES;
611     }
612   else if (addrlen != sizeof(struct IPv6UdpAddress))
613     {
614       GNUNET_break_op(0);
615       return -1; /* Must have an address to send to */
616     }
617
618   sent = 0;
619   if ( (other_peer_natd == GNUNET_YES) &&
620        (addrlen == sizeof(struct IPv4UdpAddress)) )
621     {
622       peer_session = find_session(plugin, target);
623       if (peer_session == NULL) /* We have a new peer to add */
624         {
625           /*
626            * The first time, we can assume we have no knowledge of a
627            * working port for this peer, call the ICMP/UDP message sender
628            * and wait...
629            */
630           peer_session = GNUNET_malloc(sizeof(struct PeerSession));
631           peer_session->connect_addr = GNUNET_malloc(addrlen);
632           memcpy(peer_session->connect_addr, addr, addrlen);
633           peer_session->connect_alen = addrlen;
634           peer_session->plugin = plugin;
635           peer_session->sock = NULL;
636           memcpy(&peer_session->target, target, sizeof(struct GNUNET_PeerIdentity));
637           peer_session->expecting_welcome = GNUNET_YES;
638
639           peer_session->next = plugin->sessions;
640           plugin->sessions = peer_session;
641
642           peer_session->messages = GNUNET_malloc(sizeof(struct MessageQueue));
643           peer_session->messages->msgbuf = GNUNET_malloc(msgbuf_size);
644           memcpy(peer_session->messages->msgbuf, msgbuf, msgbuf_size);
645           peer_session->messages->msgbuf_size = msgbuf_size;
646           peer_session->messages->timeout = GNUNET_TIME_relative_to_absolute(timeout);
647           peer_session->messages->cont = cont;
648           peer_session->messages->cont_cls = cont_cls;
649 #if DEBUG_UDP
650           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
651                           _("Other peer is NAT'd, set up peer session for peer %s\n"), GNUNET_i2s(target));
652 #endif
653           memset (&sin4, 0, sizeof (sin4));
654           sin4.sin_family = AF_INET;
655 #if HAVE_SOCKADDR_IN_SIN_LEN
656           sin4.sin_len = sizeof (sin4);
657 #endif
658           sin4.sin_port = t4->u4_port;
659           sin4.sin_addr.s_addr = t4->ipv4_addr;
660           GNUNET_NAT_run_client (plugin->nat, &sin4);
661         }
662       else
663         {
664           if (peer_session->expecting_welcome == GNUNET_NO) /* We are "connected" */
665             {
666               sent = udp_real_send(cls,
667                                    peer_session->sock,
668                                    target,
669                                    msgbuf, msgbuf_size,
670                                    priority, timeout,
671                                    peer_session->connect_addr, peer_session->connect_alen,
672                                    cont, cont_cls);
673             }
674           else /* Haven't gotten a response from this peer, queue message */
675             {
676               temp_message = GNUNET_malloc(sizeof(struct MessageQueue));
677               temp_message->msgbuf = GNUNET_malloc(msgbuf_size);
678               memcpy(temp_message->msgbuf, msgbuf, msgbuf_size);
679               temp_message->msgbuf_size = msgbuf_size;
680               temp_message->timeout = GNUNET_TIME_relative_to_absolute(timeout);
681               temp_message->cont = cont;
682               temp_message->cont_cls = cont_cls;
683               temp_message->next = peer_session->messages;
684               peer_session->messages = temp_message;
685             }
686         }
687     }
688   else if (other_peer_natd == GNUNET_NO) /* Other peer not behind a NAT, so we can just send the message as is */
689     {
690       sent = udp_real_send(cls,
691                            (addrlen == sizeof (struct IPv4UdpAddress)) ? plugin->udp_sockv4.desc : plugin->udp_sockv6.desc,
692                            target,
693                            msgbuf, msgbuf_size,
694                            priority, timeout, addr, addrlen,
695                            cont, cont_cls);
696     }
697   else /* Other peer is NAT'd, but we don't want to play with them (or can't!) */
698     {
699       return GNUNET_SYSERR;
700     }
701
702   /* When GNUNET_SYSERR is returned from udp_real_send, we will still call
703    * the callback so must not return GNUNET_SYSERR!
704    * If we did, then transport context would get freed twice. */
705   if (sent == GNUNET_SYSERR)
706     return 0;
707   return sent;
708 }
709
710
711 /**
712  * Send UDP probe messages or UDP keepalive messages, depending on the
713  * state of the connection.
714  *
715  * @param cls closure for this call (should be the main Plugin)
716  * @param tc task context for running this
717  */
718 static void
719 send_udp_probe_message (void *cls, 
720                         const struct GNUNET_SCHEDULER_TaskContext *tc)
721 {
722   struct UDP_NAT_Probes *probe = cls;
723   struct UDP_NAT_ProbeMessage message;
724   struct Plugin *plugin = probe->plugin;
725
726   memset (&message, 0, sizeof (message));
727   message.header.size = htons(sizeof(struct UDP_NAT_ProbeMessage));
728   message.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE);
729   /* If they gave us a port, use that.  If not, try our port. */
730   if (ntohs(probe->addr.u4_port) == 0)
731     probe->addr.u4_port = htons(plugin->port);
732
733 #if DEBUG_UDP
734       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
735                       _("Sending a probe to port %d\n"), ntohs(probe->addr.u4_port));
736 #endif
737   probe->count++;
738   udp_real_send(plugin,
739                 plugin->udp_sockv4.desc,
740                 NULL,
741                 (char *)&message, ntohs(message.header.size), 0,
742                 GNUNET_TIME_relative_get_unit(),
743                 &probe->addr, sizeof(struct IPv4UdpAddress),
744                 &udp_probe_continuation, probe);
745 }
746
747
748 /**
749  * Continuation for probe sends.  If the last probe was sent
750  * "successfully", schedule sending of another one.  If not,
751  * FIXME...
752  */
753 static void
754 udp_probe_continuation (void *cls, 
755                         const struct GNUNET_PeerIdentity *target, 
756                         int result)
757 {
758   struct UDP_NAT_Probes *probe = cls;
759   /*struct Plugin *plugin = probe->plugin;*/
760
761   if ((result == GNUNET_OK) && (probe->count < MAX_PROBES))
762     {
763 #if DEBUG_UDP
764       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
765                   _("Scheduling next probe for 10000 milliseconds\n"));
766 #endif
767       probe->task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 10), 
768                                                  &send_udp_probe_message, probe);
769     }
770   else /* Destroy the probe context. */
771     {
772 #if DEBUG_UDP
773       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
774                   _("Sending probe didn't go well...\n"));
775 #endif
776     }
777 }
778
779
780 /**
781  * FIXME.
782  */
783 static void
784 udp_plugin_reversal_callback (void *cls,
785                               const struct sockaddr *addr,
786                               socklen_t addrlen)
787 {
788   struct Plugin *plugin = cls;
789   struct UDP_NAT_Probes *temp_probe;
790   const struct sockaddr_in *inaddr;
791
792   if (sizeof (struct sockaddr_in) != addrlen)
793     {
794       GNUNET_break (0);
795       return;
796     }
797   inaddr = (const struct sockaddr_in *) addr;
798   temp_probe = GNUNET_malloc(sizeof(struct UDP_NAT_Probes));
799   temp_probe->addr.ipv4_addr = inaddr->sin_addr.s_addr;
800   temp_probe->addr.u4_port = inaddr->sin_port;
801   temp_probe->next = plugin->probes;
802   temp_probe->plugin = plugin;
803   temp_probe->task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 500), 
804                                                   &send_udp_probe_message, 
805                                                   temp_probe);
806   plugin->probes = temp_probe;
807 }
808
809
810 /**
811  * Demultiplexer for UDP NAT messages
812  *
813  * @param plugin the main plugin for this transport
814  * @param sender from which peer the message was received
815  * @param currhdr pointer to the header of the message
816  * @param sender_addr the address from which the message was received
817  * @param fromlen the length of the address
818  * @param sockinfo which socket did we receive the message on
819  */
820 static void
821 udp_demultiplexer(struct Plugin *plugin, 
822                   struct GNUNET_PeerIdentity *sender,
823                   const struct GNUNET_MessageHeader *currhdr,
824                   const void *sender_addr,
825                   size_t fromlen, struct UDP_Sock_Info *sockinfo)
826 {
827   struct UDP_NAT_ProbeMessageReply *outgoing_probe_reply;
828   struct PeerSession *peer_session;
829   struct MessageQueue *pending_message;
830   struct MessageQueue *pending_message_temp;
831   uint16_t incoming_port;
832   struct GNUNET_TRANSPORT_ATS_Information distance[2];
833   if (memcmp(sender, plugin->env->my_identity, sizeof(struct GNUNET_PeerIdentity)) == 0)
834     {
835 #if DEBUG_UDP
836       GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp",
837                       _("Received a message from myself, dropping!!!\n"));
838 #endif
839       return;
840     }
841
842   incoming_port = 0;
843   GNUNET_assert(sender_addr != NULL); /* Can recvfrom have a NULL address? */
844   if (fromlen == sizeof(struct IPv4UdpAddress))
845     {
846       incoming_port = ntohs(((struct IPv4UdpAddress *)sender_addr)->u4_port);
847     }
848   else if (fromlen == sizeof(struct IPv6UdpAddress))
849     {
850       incoming_port = ntohs(((struct IPv6UdpAddress *)sender_addr)->u6_port);
851     }
852
853   switch (ntohs(currhdr->type))
854   {
855     case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE:
856       /* Send probe reply */
857       outgoing_probe_reply = GNUNET_malloc(sizeof(struct UDP_NAT_ProbeMessageReply));
858       outgoing_probe_reply->header.size = htons(sizeof(struct UDP_NAT_ProbeMessageReply));
859       outgoing_probe_reply->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_REPLY);
860
861 #if DEBUG_UDP
862       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
863                   _("Received a probe on listen port %d, sent_from port %d\n"),
864                    sockinfo->port, incoming_port);
865 #endif
866
867       udp_real_send(plugin, sockinfo->desc, NULL,
868                     (char *)outgoing_probe_reply,
869                     ntohs(outgoing_probe_reply->header.size), 0,
870                     GNUNET_TIME_relative_get_unit(),
871                     sender_addr, fromlen,
872                     NULL, NULL);
873
874 #if DEBUG_UDP
875       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
876                   _("Sent PROBE REPLY to port %d on outgoing port %d\n"),
877                    incoming_port, sockinfo->port);
878 #endif
879       GNUNET_free(outgoing_probe_reply);
880       break;
881     case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_REPLY:
882       /* Check for existing probe, check ports returned, send confirmation if all is well */
883 #if DEBUG_UDP
884       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
885                   _("Received PROBE REPLY from port %d on incoming port %d\n"), incoming_port, sockinfo->port);
886 #endif
887       if (fromlen == sizeof(struct IPv4UdpAddress))
888         {
889           /* FIXME! */
890 #if 0
891   struct UDP_NAT_ProbeMessageConfirmation *outgoing_probe_confirmation;
892   struct UDP_NAT_Probes *outgoing_probe;
893           outgoing_probe = find_probe(plugin, &addr_buf[0]);
894           if (outgoing_probe != NULL)
895             {
896 #if DEBUG_UDP
897               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
898                           _("Sending confirmation that we were reached!\n"));
899 #endif
900               outgoing_probe_confirmation = GNUNET_malloc(sizeof(struct UDP_NAT_ProbeMessageConfirmation));
901               outgoing_probe_confirmation->header.size = htons(sizeof(struct UDP_NAT_ProbeMessageConfirmation));
902               outgoing_probe_confirmation->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_CONFIRM);
903               udp_real_send(plugin, sockinfo->desc, NULL,
904                             (char *)outgoing_probe_confirmation,
905                             ntohs(outgoing_probe_confirmation->header.size), 0,
906                             GNUNET_TIME_relative_get_unit(),
907                             sender_addr, fromlen, NULL, NULL);
908
909               if (outgoing_probe->task != GNUNET_SCHEDULER_NO_TASK)
910                 {
911                   GNUNET_SCHEDULER_cancel(outgoing_probe->task);
912                   outgoing_probe->task = GNUNET_SCHEDULER_NO_TASK;
913                   /* Schedule task to timeout and remove probe if confirmation not received */
914                 }
915               GNUNET_free(outgoing_probe_confirmation);
916             }
917           else
918             {
919 #if DEBUG_UDP
920               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
921                           _("Received a probe reply, but have no record of a sent probe!\n"));
922 #endif
923             }
924 #endif
925         }
926       else
927         {
928 #if DEBUG_UDP
929           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
930                       _("Received a probe reply, but sender address size is WRONG (should be %d, is %d)!\n"), sizeof(struct IPv4UdpAddress), fromlen);
931 #endif
932         }
933       break;
934     case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_CONFIRM:
935       peer_session = find_session(plugin, sender);
936 #if DEBUG_UDP
937           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
938                       _("Looking up peer session for peer %s\n"), GNUNET_i2s(sender));
939 #endif
940       if (peer_session == NULL) /* Shouldn't this NOT happen? */
941         {
942 #if DEBUG_UDP
943           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
944                       _("Peer not in list, adding (THIS MAY BE A MISTAKE) %s\n"), GNUNET_i2s(sender));
945 #endif
946           peer_session = GNUNET_malloc(sizeof(struct PeerSession));
947           peer_session->connect_addr = GNUNET_malloc(fromlen);
948           memcpy(peer_session->connect_addr, sender_addr, fromlen);
949           peer_session->connect_alen = fromlen;
950           peer_session->plugin = plugin;
951           peer_session->sock = sockinfo->desc;
952           memcpy(&peer_session->target, sender, sizeof(struct GNUNET_PeerIdentity));
953           peer_session->expecting_welcome = GNUNET_NO;
954
955           peer_session->next = plugin->sessions;
956           plugin->sessions = peer_session;
957
958           peer_session->messages = NULL;
959         }
960       else if (peer_session->expecting_welcome == GNUNET_YES)
961         {
962           peer_session->expecting_welcome = GNUNET_NO;
963           peer_session->sock = sockinfo->desc;
964           if (peer_session->connect_alen == sizeof(struct IPv4UdpAddress))
965             {
966               ((struct IPv4UdpAddress *)peer_session->connect_addr)->u4_port = htons(incoming_port);
967             }
968           else if (peer_session->connect_alen == sizeof(struct IPv4UdpAddress))
969             {
970               ((struct IPv6UdpAddress *)peer_session->connect_addr)->u6_port = htons(incoming_port);
971             }
972
973 #if DEBUG_UDP
974               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
975                           _("Received a probe confirmation, will send to peer on port %d\n"), incoming_port);
976 #endif
977           if (peer_session->messages != NULL)
978             {
979 #if DEBUG_UDP
980               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
981                           _("Received a probe confirmation, sending queued messages.\n"));
982 #endif
983               pending_message = peer_session->messages;
984               int count = 0;
985               while (pending_message != NULL)
986                 {
987 #if DEBUG_UDP
988                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
989                               _("sending queued message %d\n"), count);
990 #endif
991                   udp_real_send(plugin,
992                                 peer_session->sock,
993                                 &peer_session->target,
994                                 pending_message->msgbuf,
995                                 pending_message->msgbuf_size, 0,
996                                 GNUNET_TIME_relative_get_unit(),
997                                 peer_session->connect_addr,
998                                 peer_session->connect_alen,
999                                 pending_message->cont,
1000                                 pending_message->cont_cls);
1001
1002                   pending_message_temp = pending_message;
1003                   pending_message = pending_message->next;
1004                   GNUNET_free(pending_message_temp->msgbuf);
1005                   GNUNET_free(pending_message_temp);
1006 #if DEBUG_UDP
1007                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1008                               _("finished sending queued message %d\n"), count);
1009 #endif
1010                   count++;
1011                 }
1012             }
1013
1014         }
1015       else
1016         {
1017 #if DEBUG_UDP
1018           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1019                       _("Received probe confirmation for already confirmed peer!\n"));
1020 #endif
1021         }
1022       /* Received confirmation, add peer with address/port specified */
1023       break;
1024     case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_KEEPALIVE:
1025       /* Once we've sent NAT_PROBE_CONFIRM change to sending keepalives */
1026       /* If we receive these just ignore! */
1027       break;
1028     default:
1029
1030 #if DEBUG_UDP
1031       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1032                   "Sending message type %d to transport!\n",
1033                   ntohs(currhdr->type));
1034 #endif
1035
1036       distance[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
1037       distance[0].value = htonl (UDP_DIRECT_DISTANCE);
1038       distance[1].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
1039       distance[1].value = htonl (0);
1040
1041       plugin->env->receive (plugin->env->cls, sender, currhdr,
1042                     (const struct GNUNET_TRANSPORT_ATS_Information *) &distance, 2,
1043                             NULL, sender_addr, fromlen);
1044   }
1045
1046 }
1047
1048
1049 /*
1050  * We have been notified that our writeset has something to read.  We don't
1051  * know which socket needs to be read, so we have to check each one
1052  * Then reschedule this function to be called again once more is available.
1053  *
1054  * @param cls the plugin handle
1055  * @param tc the scheduling context (for rescheduling this function again)
1056  */
1057 static void
1058 udp_plugin_select (void *cls,
1059                    const struct GNUNET_SCHEDULER_TaskContext *tc)
1060 {
1061   struct Plugin *plugin = cls;
1062   char buf[65536];
1063   struct UDPMessage *msg;
1064   struct GNUNET_PeerIdentity sender;
1065   socklen_t fromlen;
1066   char addr[32];
1067   ssize_t ret;
1068   int offset;
1069   int tsize;
1070   char *msgbuf;
1071   const struct GNUNET_MessageHeader *currhdr;
1072   struct IPv4UdpAddress t4;
1073   struct IPv6UdpAddress t6;
1074   const struct sockaddr_in *s4;
1075   const struct sockaddr_in6 *s6;
1076   const void *ca;
1077   size_t calen;
1078   struct UDP_Sock_Info *udp_sock;
1079   uint16_t csize;
1080
1081   plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
1082   if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
1083     return;
1084   udp_sock = NULL;
1085   if (GNUNET_NETWORK_fdset_isset (tc->read_ready,
1086                                   plugin->udp_sockv4.desc))
1087     udp_sock = &plugin->udp_sockv4;
1088   else if (GNUNET_NETWORK_fdset_isset (tc->read_ready,
1089                                        plugin->udp_sockv6.desc))
1090     udp_sock = &plugin->udp_sockv6;
1091   if (NULL == udp_sock)
1092     {
1093       GNUNET_break (0);
1094       return;
1095     }
1096   fromlen = sizeof (addr);
1097   memset (&addr, 0, sizeof(addr));
1098   ret =
1099     GNUNET_NETWORK_socket_recvfrom (udp_sock->desc, buf, sizeof (buf),
1100                                     (struct sockaddr *)&addr, &fromlen);
1101
1102   if (AF_INET == ((struct sockaddr *)addr)->sa_family)
1103     {
1104       s4 = (const struct sockaddr_in*) &addr;
1105       t4.u4_port = s4->sin_port;
1106       t4.ipv4_addr = s4->sin_addr.s_addr;
1107       ca = &t4;
1108       calen = sizeof (t4);
1109     }
1110   else if (AF_INET6 == ((struct sockaddr *)addr)->sa_family)
1111     {
1112       s6 = (const struct sockaddr_in6*) &addr;
1113       t6.u6_port = s6->sin6_port;
1114       memcpy (&t6.ipv6_addr,
1115               &s6->sin6_addr,
1116               sizeof (struct in6_addr));
1117       ca = &t6;
1118       calen = sizeof (t6);
1119     }
1120   else
1121     {
1122       GNUNET_break (0);
1123       ca = NULL;
1124       calen = 0;
1125     }
1126   if (ret < sizeof (struct UDPMessage))
1127     {
1128       GNUNET_break_op (0);
1129       plugin->select_task =
1130         GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1131                                      GNUNET_SCHEDULER_NO_TASK,
1132                                      GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
1133                                      NULL, &udp_plugin_select, plugin);
1134       return;
1135     }
1136   msg = (struct UDPMessage *) buf;
1137   csize = ntohs (msg->header.size);
1138   if ( (csize < sizeof (struct UDPMessage)) ||
1139        (csize > ret) )
1140     {
1141       GNUNET_break_op (0);
1142       plugin->select_task =
1143         GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1144                                      GNUNET_SCHEDULER_NO_TASK,
1145                                      GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
1146                                      NULL, &udp_plugin_select, plugin);
1147       return;
1148     }
1149   msgbuf = (char *)&msg[1];
1150   memcpy (&sender, &msg->sender, sizeof (struct GNUNET_PeerIdentity));
1151   offset = 0;
1152   tsize = csize - sizeof (struct UDPMessage);
1153   while (offset + sizeof (struct GNUNET_MessageHeader) <= tsize)
1154     {
1155       currhdr = (struct GNUNET_MessageHeader *)&msgbuf[offset];
1156       csize = ntohs (currhdr->size);
1157       if ( (csize < sizeof (struct GNUNET_MessageHeader)) ||
1158            (csize > tsize - offset) )
1159         {
1160           GNUNET_break_op (0);
1161           break;
1162         }
1163       udp_demultiplexer(plugin, &sender, currhdr, 
1164                         ca, calen, udp_sock);
1165       offset += csize;
1166     }
1167   plugin->select_task =
1168     GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1169                                  GNUNET_SCHEDULER_NO_TASK,
1170                                  GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
1171                                  NULL, &udp_plugin_select, plugin);
1172
1173 }
1174
1175
1176 /**
1177  * Check if the given port is plausible (must be either
1178  * our listen port or our advertised port).  If it is
1179  * neither, we return GNUNET_SYSERR.
1180  *
1181  * @param plugin global variables
1182  * @param in_port port number to check
1183  * @return GNUNET_OK if port is either open_port or adv_port
1184  */
1185 static int
1186 check_port (struct Plugin *plugin, uint16_t in_port)
1187 {
1188   if (in_port == 0)
1189     return GNUNET_OK;
1190   if (in_port == plugin->port)
1191     return GNUNET_OK;
1192   return GNUNET_SYSERR;
1193 }
1194
1195
1196 /**
1197  * Function that will be called to check if a binary address for this
1198  * plugin is well-formed and corresponds to an address for THIS peer
1199  * (as per our configuration).  Naturally, if absolutely necessary,
1200  * plugins can be a bit conservative in their answer, but in general
1201  * plugins should make sure that the address does not redirect
1202  * traffic to a 3rd party that might try to man-in-the-middle our
1203  * traffic.
1204  *
1205  * @param cls closure, should be our handle to the Plugin
1206  * @param addr pointer to the address
1207  * @param addrlen length of addr
1208  * @return GNUNET_OK if this is a plausible address for this peer
1209  *         and transport, GNUNET_SYSERR if not
1210  *
1211  */
1212 static int
1213 udp_plugin_check_address (void *cls,
1214                           const void *addr,
1215                           size_t addrlen)
1216 {
1217   struct Plugin *plugin = cls;
1218   struct IPv4UdpAddress *v4;
1219   struct IPv6UdpAddress *v6;
1220
1221   if ((addrlen != sizeof (struct IPv4UdpAddress)) &&
1222       (addrlen != sizeof (struct IPv6UdpAddress)))
1223     {
1224       GNUNET_break_op (0);
1225       return GNUNET_SYSERR;
1226     }
1227   if (addrlen == sizeof (struct IPv4UdpAddress))
1228     {
1229       v4 = (struct IPv4UdpAddress *) addr;
1230       if (GNUNET_OK !=
1231           check_port (plugin, ntohs (v4->u4_port)))
1232         return GNUNET_SYSERR;
1233       if (GNUNET_OK !=
1234           GNUNET_NAT_test_address (plugin->nat, 
1235                                    &v4->ipv4_addr, sizeof (struct in_addr)))
1236         return GNUNET_SYSERR;
1237     }
1238   else
1239     {
1240       v6 = (struct IPv6UdpAddress *) addr;
1241       if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr))
1242         {
1243           GNUNET_break_op (0);
1244           return GNUNET_SYSERR;
1245         }
1246       if (GNUNET_OK !=
1247           check_port (plugin, ntohs (v6->u6_port)))
1248         return GNUNET_SYSERR;
1249       if (GNUNET_OK !=
1250           GNUNET_NAT_test_address (plugin->nat,
1251                                    &v6->ipv6_addr, sizeof (struct in6_addr)))
1252         return GNUNET_SYSERR;
1253     }
1254   return GNUNET_OK;
1255 }
1256
1257
1258 /**
1259  * Append our port and forward the result.
1260  */
1261 static void
1262 append_port (void *cls, const char *hostname)
1263 {
1264   struct PrettyPrinterContext *ppc = cls;
1265   char *ret;
1266
1267   if (hostname == NULL)
1268     {
1269       ppc->asc (ppc->asc_cls, NULL);
1270       GNUNET_free (ppc);
1271       return;
1272     }
1273   GNUNET_asprintf (&ret, "%s:%d", hostname, ppc->port);
1274   ppc->asc (ppc->asc_cls, ret);
1275   GNUNET_free (ret);
1276 }
1277
1278
1279 /**
1280  * Convert the transports address to a nice, human-readable
1281  * format.
1282  *
1283  * @param cls closure
1284  * @param type name of the transport that generated the address
1285  * @param addr one of the addresses of the host, NULL for the last address
1286  *        the specific address format depends on the transport
1287  * @param addrlen length of the address
1288  * @param numeric should (IP) addresses be displayed in numeric form?
1289  * @param timeout after how long should we give up?
1290  * @param asc function to call on each string
1291  * @param asc_cls closure for asc
1292  */
1293 static void
1294 udp_plugin_address_pretty_printer (void *cls,
1295                                    const char *type,
1296                                    const void *addr,
1297                                    size_t addrlen,
1298                                    int numeric,
1299                                    struct GNUNET_TIME_Relative timeout,
1300                                    GNUNET_TRANSPORT_AddressStringCallback asc,
1301                                    void *asc_cls)
1302 {
1303   struct PrettyPrinterContext *ppc;
1304   const void *sb;
1305   size_t sbs;
1306   struct sockaddr_in a4;
1307   struct sockaddr_in6 a6;
1308   const struct IPv4UdpAddress *u4;
1309   const struct IPv6UdpAddress *u6;
1310   uint16_t port;
1311
1312   if (addrlen == sizeof (struct IPv6UdpAddress))
1313     {
1314       u6 = addr;
1315       memset (&a6, 0, sizeof (a6));
1316       a6.sin6_family = AF_INET6;
1317       a6.sin6_port = u6->u6_port;
1318       memcpy (&a6.sin6_addr,
1319               &u6->ipv6_addr,
1320               sizeof (struct in6_addr));
1321       port = ntohs (u6->u6_port);
1322       sb = &a6;
1323       sbs = sizeof (a6);
1324     }
1325   else if (addrlen == sizeof (struct IPv4UdpAddress))
1326     {
1327       u4 = addr;
1328       memset (&a4, 0, sizeof (a4));
1329       a4.sin_family = AF_INET;
1330       a4.sin_port = u4->u4_port;
1331       a4.sin_addr.s_addr = u4->ipv4_addr;
1332       port = ntohs (u4->u4_port);
1333       sb = &a4;
1334       sbs = sizeof (a4);
1335     }
1336   else
1337     {
1338       /* invalid address */
1339       GNUNET_break_op (0);
1340       asc (asc_cls, NULL);
1341       return;
1342     }
1343   ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext));
1344   ppc->asc = asc;
1345   ppc->asc_cls = asc_cls;
1346   ppc->port = port;
1347   GNUNET_RESOLVER_hostname_get (sb,
1348                                 sbs,
1349                                 !numeric, timeout, &append_port, ppc);
1350 }
1351
1352
1353 /**
1354  * Function called for a quick conversion of the binary address to
1355  * a numeric address.  Note that the caller must not free the
1356  * address and that the next call to this function is allowed
1357  * to override the address again.
1358  *
1359  * @param cls closure
1360  * @param addr binary address
1361  * @param addrlen length of the address
1362  * @return string representing the same address
1363  */
1364 static const char*
1365 udp_address_to_string (void *cls,
1366                        const void *addr,
1367                        size_t addrlen)
1368 {
1369   static char rbuf[INET6_ADDRSTRLEN + 10];
1370   char buf[INET6_ADDRSTRLEN];
1371   const void *sb;
1372   struct in_addr a4;
1373   struct in6_addr a6;
1374   const struct IPv4UdpAddress *t4;
1375   const struct IPv6UdpAddress *t6;
1376   int af;
1377   uint16_t port;
1378
1379   if (addrlen == sizeof (struct IPv6UdpAddress))
1380     {
1381       t6 = addr;
1382       af = AF_INET6;
1383       port = ntohs (t6->u6_port);
1384       memcpy (&a6, &t6->ipv6_addr, sizeof (a6));
1385       sb = &a6;
1386     }
1387   else if (addrlen == sizeof (struct IPv4UdpAddress))
1388     {
1389       t4 = addr;
1390       af = AF_INET;
1391       port = ntohs (t4->u4_port);
1392       memcpy (&a4, &t4->ipv4_addr, sizeof (a4));
1393       sb = &a4;
1394     }
1395   else
1396     return NULL;
1397   inet_ntop (af, sb, buf, INET6_ADDRSTRLEN);
1398   GNUNET_snprintf (rbuf,
1399                    sizeof (rbuf),
1400                    "%s:%u",
1401                    buf,
1402                    port);
1403   return rbuf;
1404 }
1405
1406
1407 /**
1408  * Our external IP address/port mapping has changed.
1409  *
1410  * @param cls closure, the 'struct LocalAddrList'
1411  * @param add_remove GNUNET_YES to mean the new public IP address, GNUNET_NO to mean
1412  *     the previous (now invalid) one
1413  * @param addr either the previous or the new public IP address
1414  * @param addrlen actual lenght of the address
1415  */
1416 static void
1417 udp_nat_port_map_callback (void *cls,
1418                        int add_remove,
1419                        const struct sockaddr *addr,
1420                        socklen_t addrlen)
1421 {
1422   struct Plugin *plugin = cls;
1423   struct IPv4UdpAddress u4;
1424   struct IPv6UdpAddress u6;
1425   void *arg;
1426   size_t args;
1427
1428   /* convert 'addr' to our internal format */
1429   switch (addr->sa_family)
1430     {
1431     case AF_INET:
1432       GNUNET_assert (addrlen == sizeof (struct sockaddr_in));
1433       u4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
1434       u4.u4_port = ((struct sockaddr_in *) addr)->sin_port;
1435       arg = &u4;
1436       args = sizeof (u4);
1437       break;
1438     case AF_INET6:
1439       GNUNET_assert (addrlen == sizeof (struct sockaddr_in6));
1440       memcpy (&u6.ipv6_addr,
1441               &((struct sockaddr_in6 *) addr)->sin6_addr,
1442               sizeof (struct in6_addr));
1443       u6.u6_port = ((struct sockaddr_in6 *) addr)->sin6_port;
1444       arg = &u6;
1445       args = sizeof (u6);    
1446       break;
1447     default:
1448       GNUNET_break (0);
1449       return;
1450     }
1451   /* modify our published address list */
1452   plugin->env->notify_address (plugin->env->cls,
1453                                add_remove,
1454                                arg, args);
1455 }
1456
1457
1458 /**
1459  * The exported method. Makes the core api available via a global and
1460  * returns the udp transport API.
1461  */
1462 void *
1463 libgnunet_plugin_transport_udp_init (void *cls)
1464 {
1465   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
1466   unsigned long long mtu;
1467   unsigned long long port;
1468   struct GNUNET_TRANSPORT_PluginFunctions *api;
1469   struct Plugin *plugin;
1470   int sockets_created;
1471   struct sockaddr_in serverAddrv4;
1472   struct sockaddr_in6 serverAddrv6;
1473   struct sockaddr *serverAddr;
1474   struct sockaddr *addrs[2];
1475   socklen_t addrlens[2];
1476   socklen_t addrlen;
1477   unsigned int tries;
1478
1479   if (GNUNET_OK !=
1480       GNUNET_CONFIGURATION_get_value_number (env->cfg,
1481                                              "transport-udp",
1482                                              "PORT",
1483                                              &port))
1484     port = UDP_NAT_DEFAULT_PORT;
1485   if (port > 65535)
1486     {
1487       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1488                   _("Given `%s' option is out of range: %llu > %u\n"),
1489                   "PORT",
1490                   port,
1491                   65535);
1492       return NULL;
1493     }
1494
1495   mtu = 1240;
1496   if (mtu < 1200)
1497     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1498                 _("MTU %llu for `%s' is probably too low!\n"), mtu,
1499                 "UDP");
1500   plugin = GNUNET_malloc (sizeof (struct Plugin));
1501   plugin->port = port;
1502   plugin->env = env;
1503   api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
1504   api->cls = plugin;
1505
1506   api->send = &udp_plugin_send;
1507   api->disconnect = &udp_disconnect;
1508   api->address_pretty_printer = &udp_plugin_address_pretty_printer;
1509   api->address_to_string = &udp_address_to_string;
1510   api->check_address = &udp_plugin_check_address;
1511
1512   if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string(env->cfg, 
1513                                                           "transport-udp", 
1514                                                           "BINDTO", 
1515                                                           &plugin->bind_address))
1516     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 
1517                "Binding udp plugin to specific address: `%s'\n", 
1518                plugin->bind_address);
1519   if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string(env->cfg, 
1520                                                           "transport-udp",
1521                                                           "BINDTO6", 
1522                                                           &plugin->bind6_address))
1523     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1524                "Binding udp plugin to specific address: `%s'\n",
1525                plugin->bind6_address);
1526
1527   sockets_created = 0;
1528   if ( (GNUNET_YES !=
1529         GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg,
1530                                               "gnunetd",
1531                                               "DISABLEV6")))
1532     {
1533       plugin->udp_sockv6.desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 0);
1534       if (NULL == plugin->udp_sockv6.desc)
1535         {
1536           GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp", "socket");
1537         }
1538       else
1539         {
1540           memset (&serverAddrv6, 0, sizeof (serverAddrv6));
1541 #if HAVE_SOCKADDR_IN_SIN_LEN
1542           serverAddrv6.sin6_len = sizeof (serverAddrv6);
1543 #endif
1544
1545           serverAddrv6.sin6_family = AF_INET6;
1546           serverAddrv6.sin6_addr = in6addr_any;
1547           if (plugin->bind6_address != NULL)
1548             {
1549               if (1 != inet_pton(AF_INET6, plugin->bind6_address, &serverAddrv6.sin6_addr))
1550                 return 0;
1551             }
1552           serverAddrv6.sin6_port = htons (plugin->port);
1553           addrlen = sizeof (serverAddrv6);
1554           serverAddr = (struct sockaddr *) &serverAddrv6;
1555 #if DEBUG_UDP
1556           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1557                            "Binding to IPv6 port %d\n",
1558                            ntohs(serverAddrv6.sin6_port));
1559 #endif
1560           tries = 0;
1561           while (GNUNET_NETWORK_socket_bind (plugin->udp_sockv6.desc, serverAddr, addrlen) !=
1562                  GNUNET_OK)
1563             {
1564               serverAddrv6.sin6_port
1565                 = htons (GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a good, non-root port */
1566 #if DEBUG_UDP
1567               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1568                                "IPv6 Binding failed, trying new port %d\n",
1569                                ntohs(serverAddrv6.sin6_port));
1570 #endif
1571               tries++;
1572               if (tries > 10)
1573                 {
1574                   GNUNET_NETWORK_socket_close (plugin->udp_sockv6.desc);
1575                   plugin->udp_sockv6.desc = NULL;
1576                   break;
1577                 }       
1578             }
1579           if (plugin->udp_sockv6.desc != NULL)
1580             {
1581               plugin->udp_sockv6.port = ntohs(serverAddrv6.sin6_port);
1582               addrs[sockets_created] = (struct sockaddr*)  &serverAddrv6;
1583               addrlens[sockets_created] = sizeof (serverAddrv6);
1584               sockets_created++;
1585             }
1586         }
1587     }
1588
1589   plugin->udp_sockv4.desc = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 0);
1590   if (NULL == plugin->udp_sockv4.desc)
1591     {
1592       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "socket");
1593     }
1594   else
1595     {
1596       memset (&serverAddrv4, 0, sizeof (serverAddrv4));
1597 #if HAVE_SOCKADDR_IN_SIN_LEN
1598       serverAddrv4.sin_len = sizeof (serverAddrv4);
1599 #endif
1600       serverAddrv4.sin_family = AF_INET;
1601       serverAddrv4.sin_addr.s_addr = INADDR_ANY;
1602       if (plugin->bind_address != NULL)
1603         {
1604           if (1 != inet_pton(AF_INET, plugin->bind_address, &serverAddrv4.sin_addr))
1605             return 0;
1606         }
1607       serverAddrv4.sin_port = htons (plugin->port);
1608       addrlen = sizeof (serverAddrv4);
1609       serverAddr = (struct sockaddr *) &serverAddrv4;
1610 #if DEBUG_UDP
1611       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1612                        "Binding to IPv4 port %d\n",
1613                        ntohs(serverAddrv4.sin_port));
1614 #endif
1615       tries = 0;
1616       while (GNUNET_NETWORK_socket_bind (plugin->udp_sockv4.desc, serverAddr, addrlen) !=
1617              GNUNET_OK)
1618         {
1619           serverAddrv4.sin_port = htons (GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a good, non-root port */
1620 #if DEBUG_UDP
1621           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1622                            "IPv4 Binding failed, trying new port %d\n",
1623                            ntohs(serverAddrv4.sin_port));
1624 #endif
1625           tries++;
1626           if (tries > 10)
1627             {
1628               GNUNET_NETWORK_socket_close (plugin->udp_sockv4.desc);
1629               plugin->udp_sockv4.desc = NULL;
1630               break;
1631             }   
1632         }
1633       if (plugin->udp_sockv4.desc != NULL)
1634         {
1635           plugin->udp_sockv4.port = ntohs(serverAddrv4.sin_port);
1636           addrs[sockets_created] = (struct sockaddr*) &serverAddrv4;
1637           addrlens[sockets_created] = sizeof (serverAddrv4);
1638           sockets_created++;
1639         }
1640     }
1641
1642   plugin->rs = GNUNET_NETWORK_fdset_create ();
1643   GNUNET_NETWORK_fdset_zero (plugin->rs);
1644   if (NULL != plugin->udp_sockv4.desc)
1645     GNUNET_NETWORK_fdset_set (plugin->rs,
1646                               plugin->udp_sockv4.desc);
1647   if (NULL != plugin->udp_sockv6.desc)
1648     GNUNET_NETWORK_fdset_set (plugin->rs,
1649                               plugin->udp_sockv6.desc);
1650
1651   plugin->select_task =
1652     GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1653                                  GNUNET_SCHEDULER_NO_TASK,
1654                                  GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
1655                                  NULL, &udp_plugin_select, plugin);
1656   if (sockets_created == 0)
1657     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1658                 _("Failed to open UDP sockets\n"));
1659   plugin->nat = GNUNET_NAT_register (env->cfg,
1660                                      GNUNET_NO,
1661                                      port,
1662                                      sockets_created,
1663                                      (const struct sockaddr**) addrs, addrlens,
1664                                      &udp_nat_port_map_callback, 
1665                                      &udp_plugin_reversal_callback,
1666                                      plugin);
1667   return api;
1668 }
1669
1670
1671 void *
1672 libgnunet_plugin_transport_udp_done (void *cls)
1673 {
1674   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
1675   struct Plugin *plugin = api->cls;
1676
1677   if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
1678     {
1679       GNUNET_SCHEDULER_cancel (plugin->select_task);
1680       plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
1681     }
1682   if (plugin->udp_sockv4.desc != NULL)
1683     {
1684       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->udp_sockv4.desc));
1685       plugin->udp_sockv4.desc = NULL;
1686     }
1687   if (plugin->udp_sockv6.desc != NULL)
1688     {
1689       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->udp_sockv6.desc));
1690       plugin->udp_sockv6.desc = NULL;
1691     }
1692   GNUNET_NETWORK_fdset_destroy (plugin->rs);
1693   GNUNET_NAT_unregister (plugin->nat);
1694   plugin->nat = NULL;
1695   GNUNET_free (plugin);
1696   GNUNET_free (api);
1697   return NULL;
1698 }
1699
1700 /* end of plugin_transport_udp.c */