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