unix domain socket transport, associated test cases
[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_os_lib.h"
45 #include "gnunet_peerinfo_service.h"
46 #include "gnunet_protocols.h"
47 #include "gnunet_resolver_service.h"
48 #include "gnunet_server_lib.h"
49 #include "gnunet_signatures.h"
50 #include "gnunet_statistics_service.h"
51 #include "gnunet_transport_service.h"
52 #include "gnunet_transport_plugin.h"
53 #include "transport.h"
54
55 #define DEBUG_UDP GNUNET_YES
56
57 #define MAX_PROBES 20
58
59 /*
60  * Transport cost to peer, always 1 for UDP (direct connection)
61  */
62 #define UDP_DIRECT_DISTANCE 1
63
64 #define DEFAULT_NAT_PORT 0
65
66 /**
67  * How long until we give up on transmitting the welcome message?
68  */
69 #define HOSTNAME_RESOLVE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
70
71 /**
72  * Starting port for listening and sending, eventually a config value
73  */
74 #define UDP_NAT_DEFAULT_PORT 22086
75
76 /**
77  * UDP Message-Packet header.
78  */
79 struct UDPMessage
80 {
81   /**
82    * Message header.
83    */
84   struct GNUNET_MessageHeader header;
85
86   /**
87    * What is the identity of the sender (GNUNET_hash of public key)
88    */
89   struct GNUNET_PeerIdentity sender;
90
91 };
92
93 /**
94  * Network format for IPv4 addresses.
95  */
96 struct IPv4UdpAddress
97 {
98   /**
99    * IPv4 address, in network byte order.
100    */
101   uint32_t ipv4_addr GNUNET_PACKED;
102
103   /**
104    * Port number, in network byte order.
105    */
106   uint16_t u_port GNUNET_PACKED;
107 };
108
109
110 /**
111  * Network format for IPv6 addresses.
112  */
113 struct IPv6UdpAddress
114 {
115   /**
116    * IPv6 address.
117    */
118   struct in6_addr ipv6_addr GNUNET_PACKED;
119
120   /**
121    * Port number, in network byte order.
122    */
123   uint16_t u6_port GNUNET_PACKED;
124 };
125
126 /* Forward definition */
127 struct Plugin;
128
129 struct PrettyPrinterContext
130 {
131   GNUNET_TRANSPORT_AddressStringCallback asc;
132   void *asc_cls;
133   uint16_t port;
134 };
135
136 struct MessageQueue
137 {
138   /**
139    * Linked List
140    */
141   struct MessageQueue *next;
142
143   /**
144    * Session this message belongs to
145    */
146   struct PeerSession *session;
147
148   /**
149    * Actual message to be sent
150    */
151   char *msgbuf;
152
153   /**
154    * Size of message buffer to be sent
155    */
156   size_t msgbuf_size;
157
158   /**
159    * When to discard this message
160    */
161   struct GNUNET_TIME_Absolute timeout;
162
163   /**
164    * Continuation to call when this message goes out
165    */
166   GNUNET_TRANSPORT_TransmitContinuation cont;
167
168   /**
169    * closure for continuation
170    */
171   void *cont_cls;
172
173 };
174
175 /**
176  * UDP NAT Probe message definition
177  */
178 struct UDP_NAT_ProbeMessage
179 {
180   /**
181    * Message header
182    */
183   struct GNUNET_MessageHeader header;
184
185 };
186
187 /**
188  * UDP NAT Probe message reply definition
189  */
190 struct UDP_NAT_ProbeMessageReply
191 {
192   /**
193    * Message header
194    */
195   struct GNUNET_MessageHeader header;
196
197 };
198
199
200 /**
201  * UDP NAT Probe message confirm definition
202  */
203 struct UDP_NAT_ProbeMessageConfirmation
204 {
205   /**
206    * Message header
207    */
208   struct GNUNET_MessageHeader header;
209
210 };
211
212
213 /**
214  * Local network addresses (actual IP address follows this struct).
215  * PORT is NOT included!
216  */
217 struct LocalAddrList
218 {
219
220   /**
221    * This is a doubly linked list.
222    */
223   struct LocalAddrList *next;
224
225   /**
226    * This is a doubly linked list.
227    */
228   struct LocalAddrList *prev;
229
230   /**
231    * Number of bytes of the address that follow
232    */
233   size_t size;
234
235 };
236
237
238 /**
239  * UDP NAT "Session"
240  */
241 struct PeerSession
242 {
243
244   /**
245    * Stored in a linked list.
246    */
247   struct PeerSession *next;
248
249   /**
250    * Pointer to the global plugin struct.
251    */
252   struct Plugin *plugin;
253
254   /**
255    * To whom are we talking to (set to our identity
256    * if we are still waiting for the welcome message)
257    */
258   struct GNUNET_PeerIdentity target;
259
260   /**
261    * Address of the other peer (either based on our 'connect'
262    * call or on our 'accept' call).
263    */
264   void *connect_addr;
265
266   /**
267    * Length of connect_addr.
268    */
269   size_t connect_alen;
270
271   /**
272    * Are we still expecting the welcome message? (GNUNET_YES/GNUNET_NO)
273    */
274   int expecting_welcome;
275
276   /**
277    * From which socket do we need to send to this peer?
278    */
279   struct GNUNET_NETWORK_Handle *sock;
280
281   /*
282    * Queue of messages for this peer, in the case that
283    * we have to await a connection...
284    */
285   struct MessageQueue *messages;
286
287 };
288
289 struct UDP_NAT_Probes
290 {
291
292   /**
293    * Linked list
294    */
295   struct UDP_NAT_Probes *next;
296
297   /**
298    * Address string that the server process returned to us
299    */
300   char *address_string;
301
302   /**
303    * Timeout for this set of probes
304    */
305   struct GNUNET_TIME_Absolute timeout;
306
307   /**
308    * Count of how many probes we've attempted
309    */
310   int count;
311
312   /**
313    * The plugin this probe belongs to
314    */
315   struct Plugin *plugin;
316
317   /**
318    * The task used to send these probes
319    */
320   GNUNET_SCHEDULER_TaskIdentifier task;
321
322   /**
323    * Network address (always ipv4!)
324    */
325   struct IPv4UdpAddress addr;
326
327 };
328
329
330 /**
331  * Information we keep for each of our listen sockets.
332  */
333 struct UDP_Sock_Info
334 {
335   /**
336    * The network handle
337    */
338   struct GNUNET_NETWORK_Handle *desc;
339
340   /**
341    * The port we bound to
342    */
343   uint16_t port;
344 };
345
346
347 /**
348  * Encapsulation of all of the state of the plugin.
349  */
350 struct Plugin
351 {
352   /**
353    * Our environment.
354    */
355   struct GNUNET_TRANSPORT_PluginEnvironment *env;
356
357   /*
358    * Session of peers with whom we are currently connected
359    */
360   struct PeerSession *sessions;
361
362   /**
363    * Handle for request of hostname resolution, non-NULL if pending.
364    */
365   struct GNUNET_RESOLVER_RequestHandle *hostname_dns;
366
367   /**
368    * ID of task used to update our addresses when one expires.
369    */
370   GNUNET_SCHEDULER_TaskIdentifier address_update_task;
371
372   /**
373    * ID of select task
374    */
375   GNUNET_SCHEDULER_TaskIdentifier select_task;
376
377   /**
378    * Port to listen on.
379    */
380   uint16_t port;
381
382   /**
383    * The external address given to us by the user.  Must be actual
384    * outside visible address for NAT punching to work.
385    */
386   char *external_address;
387
388   /**
389    * The internal address given to us by the user (or discovered).
390    */
391   char *internal_address;
392
393   /**
394    * Address we were told to bind to exclusively (IPv4).
395    */
396   char *bind_address;
397
398   /**
399    * Address we were told to bind to exclusively (IPv6).
400    */
401   char *bind6_address;
402
403   /**
404    * List of our IP addresses.
405    */
406   struct LocalAddrList *lal_head;
407
408   /**
409    * Tail of our IP address list.
410    */
411   struct LocalAddrList *lal_tail;
412
413   /**
414    * FD Read set
415    */
416   struct GNUNET_NETWORK_FDSet *rs;
417
418   /**
419    * stdout pipe handle for the gnunet-nat-server process
420    */
421   struct GNUNET_DISK_PipeHandle *server_stdout;
422
423   /**
424    * stdout file handle (for reading) for the gnunet-nat-server process
425    */
426   const struct GNUNET_DISK_FileHandle *server_stdout_handle;
427
428   /**
429    * Probes in flight
430    */
431   struct UDP_NAT_Probes *probes;
432
433   /**
434    * socket that we transmit all IPv4 data with
435    */
436   struct UDP_Sock_Info udp_sockv4;
437
438   /**
439    * socket that we transmit all IPv6 data with
440    */
441   struct UDP_Sock_Info udp_sockv6;
442
443   /**
444    * ID of select gnunet-nat-server stdout read task
445    */
446   GNUNET_SCHEDULER_TaskIdentifier server_read_task;
447
448   /**
449    * Is this transport configured to be behind a NAT?
450    */
451   int behind_nat;
452
453   /**
454    * Is this transport configured to allow connections to NAT'd peers?
455    */
456   int allow_nat;
457
458   /**
459    * Should this transport advertise only NAT addresses (port set to 0)?
460    * If not, all addresses will be duplicated for NAT punching and regular
461    * ports.
462    */
463   int only_nat_addresses;
464
465   /**
466    * The process id of the server process (if behind NAT)
467    */
468   struct GNUNET_OS_Process *server_proc;
469
470 };
471
472
473 /**
474  * Forward declaration.
475  */
476 void
477 udp_probe_continuation (void *cls, const struct GNUNET_PeerIdentity *target, int result);
478
479
480 /**
481  * Disconnect from a remote node.  Clean up session if we have one for this peer
482  *
483  * @param cls closure for this call (should be handle to Plugin)
484  * @param target the peeridentity of the peer to disconnect
485  * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
486  */
487 void
488 udp_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
489 {
490   /** TODO: Implement! */
491   return;
492 }
493
494 /**
495  * Shutdown the server process (stop receiving inbound traffic). Maybe
496  * restarted later!
497  *
498  * @param cls Handle to the plugin for this transport
499  *
500  * @return returns the number of sockets successfully closed,
501  *         should equal the number of sockets successfully opened
502  */
503 static int
504 udp_transport_server_stop (void *cls)
505 {
506   struct Plugin *plugin = cls;
507
508   if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
509     {
510       GNUNET_SCHEDULER_cancel (plugin->select_task);
511       plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
512     }
513   if (plugin->udp_sockv4.desc != NULL)
514     {
515       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->udp_sockv4.desc));
516       plugin->udp_sockv4.desc = NULL;
517     }
518   if (plugin->udp_sockv6.desc != NULL)
519     {
520       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->udp_sockv6.desc));
521       plugin->udp_sockv6.desc = NULL;
522     }
523   if (plugin->behind_nat == GNUNET_YES)
524     {
525       if (0 != GNUNET_OS_process_kill (plugin->server_proc, SIGTERM))
526         GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
527       GNUNET_OS_process_wait (plugin->server_proc);
528       GNUNET_OS_process_close (plugin->server_proc);
529       plugin->server_proc = NULL;
530     }
531   return GNUNET_OK;
532 }
533
534
535 struct PeerSession *
536 find_session (struct Plugin *plugin,
537               const struct GNUNET_PeerIdentity *peer)
538 {
539   struct PeerSession *pos;
540
541   pos = plugin->sessions;
542   while (pos != NULL)
543     {
544       if (memcmp(&pos->target, peer, sizeof(struct GNUNET_PeerIdentity)) == 0)
545         return pos;
546       pos = pos->next;
547     }
548
549   return pos;
550 }
551
552
553 /**
554  * Actually send out the message, assume we've got the address and
555  * send_handle squared away!
556  *
557  * @param cls closure
558  * @param send_handle which handle to send message on
559  * @param target who should receive this message (ignored by UDP)
560  * @param msgbuf one or more GNUNET_MessageHeader(s) strung together
561  * @param msgbuf_size the size of the msgbuf to send
562  * @param priority how important is the message (ignored by UDP)
563  * @param timeout when should we time out (give up) if we can not transmit?
564  * @param addr the addr to send the message to, needs to be a sockaddr for us
565  * @param addrlen the len of addr
566  * @param cont continuation to call once the message has
567  *        been transmitted (or if the transport is ready
568  *        for the next transmission call; or if the
569  *        peer disconnected...)
570  * @param cont_cls closure for cont
571  * @return the number of bytes written
572  */
573 static ssize_t
574 udp_real_send (void *cls,
575                struct GNUNET_NETWORK_Handle *send_handle,
576                const struct GNUNET_PeerIdentity *target,
577                const char *msgbuf,
578                size_t msgbuf_size,
579                unsigned int priority,
580                struct GNUNET_TIME_Relative timeout,
581                const void *addr,
582                size_t addrlen,
583                GNUNET_TRANSPORT_TransmitContinuation cont,
584                void *cont_cls)
585 {
586   struct Plugin *plugin = cls;
587   struct UDPMessage *message;
588   int ssize;
589   ssize_t sent;
590   struct sockaddr_in a4;
591   struct sockaddr_in6 a6;
592   const struct IPv4UdpAddress *t4;
593   const struct IPv6UdpAddress *t6;
594   const void *sb;
595   size_t sbs;
596
597   if (send_handle == NULL)
598     {
599       /* failed to open send socket for AF */
600       if (cont != NULL)
601         cont (cont_cls, target, GNUNET_SYSERR);
602       return 0;
603     }
604   if ((addr == NULL) || (addrlen == 0))
605     {
606 #if DEBUG_UDP
607       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
608                        "udp_real_send called without address, returning!\n");
609 #endif
610       if (cont != NULL)
611         cont (cont_cls, target, GNUNET_SYSERR);
612       return 0; /* Can never send if we don't have an address!! */
613     }
614
615   /* Build the message to be sent */
616   message = GNUNET_malloc (sizeof (struct UDPMessage) + msgbuf_size);
617   ssize = sizeof (struct UDPMessage) + msgbuf_size;
618
619   message->header.size = htons (ssize);
620   message->header.type = htons (0);
621   memcpy (&message->sender, plugin->env->my_identity,
622           sizeof (struct GNUNET_PeerIdentity));
623   memcpy (&message[1], msgbuf, msgbuf_size);
624
625   if (addrlen == sizeof (struct IPv6UdpAddress))
626     {
627       t6 = addr;
628       memset (&a6, 0, sizeof (a6));
629 #if HAVE_SOCKADDR_IN_SIN_LEN
630       a6.sin6_len = sizeof (a6);
631 #endif
632       a6.sin6_family = AF_INET6;
633       a6.sin6_port = t6->u6_port;
634       memcpy (&a6.sin6_addr,
635               &t6->ipv6_addr,
636               sizeof (struct in6_addr));
637       sb = &a6;
638       sbs = sizeof (a6);
639     }
640   else if (addrlen == sizeof (struct IPv4UdpAddress))
641     {
642       t4 = addr;
643       memset (&a4, 0, sizeof (a4));
644 #if HAVE_SOCKADDR_IN_SIN_LEN
645       a4.sin_len = sizeof (a4);
646 #endif
647       a4.sin_family = AF_INET;
648       a4.sin_port = t4->u_port;
649       a4.sin_addr.s_addr = t4->ipv4_addr;
650       sb = &a4;
651       sbs = sizeof (a4);
652     }
653   else
654     {
655       GNUNET_break_op (0);
656       GNUNET_free (message);
657       return -1;
658     }
659
660   /* Actually send the message */
661   sent =
662     GNUNET_NETWORK_socket_sendto (send_handle, message, ssize,
663                                   sb,
664                                   sbs);
665   if (GNUNET_SYSERR == sent)
666     GNUNET_log_strerror(GNUNET_ERROR_TYPE_DEBUG, "sendto");
667   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
668               "UDP transmit %u-byte message to %s (%d: %s)\n",
669               (unsigned int) ssize,
670               GNUNET_a2s (sb, sbs),
671               (int) sent,
672               (sent < 0) ? STRERROR (errno) : "ok");
673   if (cont != NULL)
674     {
675       if (sent == GNUNET_SYSERR)
676         cont (cont_cls, target, GNUNET_SYSERR);
677       else
678         {
679           cont (cont_cls, target, GNUNET_OK);
680         }
681     }
682
683   GNUNET_free (message);
684   return sent;
685 }
686
687 /**
688  * We learned about a peer (possibly behind NAT) so run the
689  * gnunet-nat-client to send dummy ICMP responses
690  *
691  * @param plugin the plugin for this transport
692  * @param addr the address of the peer
693  * @param addrlen the length of the address
694  */
695 void
696 run_gnunet_nat_client (struct Plugin *plugin, const char *addr, size_t addrlen)
697 {
698   char addr_buf[INET_ADDRSTRLEN];
699   char *address_as_string;
700   char *port_as_string;
701   struct GNUNET_OS_Process *proc;
702   const struct IPv4UdpAddress *t4;
703
704   GNUNET_assert(addrlen == sizeof(struct IPv4UdpAddress));
705   t4 = (struct IPv4UdpAddress *)addr;
706
707   if (NULL == inet_ntop (AF_INET,
708                          &t4->ipv4_addr,
709                          addr_buf, INET_ADDRSTRLEN))
710     {
711       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "inet_ntop");
712       return;
713     }
714   address_as_string = GNUNET_strdup (addr_buf);
715   GNUNET_asprintf(&port_as_string, "%d", plugin->port);
716 #if DEBUG_UDP
717   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
718                   _("Running gnunet-nat-client with arguments: %s %s %d\n"), plugin->external_address, address_as_string, plugin->port);
719 #endif
720
721   /* Start the server process */
722   proc = GNUNET_OS_start_process (NULL, NULL, "gnunet-nat-client", "gnunet-nat-client", plugin->external_address, address_as_string, port_as_string, NULL);
723   GNUNET_free(address_as_string);
724   GNUNET_free(port_as_string);
725   if (proc != NULL)
726     {
727       GNUNET_OS_process_wait (proc);
728       GNUNET_OS_process_close (proc);
729       proc = NULL;
730     }
731 }
732
733 /**
734  * Function that can be used by the transport service to transmit
735  * a message using the plugin.
736  *
737  * @param cls closure
738  * @param target who should receive this message (ignored by UDP)
739  * @param msgbuf one or more GNUNET_MessageHeader(s) strung together
740  * @param msgbuf_size the size of the msgbuf to send
741  * @param priority how important is the message (ignored by UDP)
742  * @param timeout when should we time out (give up) if we can not transmit?
743  * @param session identifier used for this session (can be NULL)
744  * @param addr the addr to send the message to, needs to be a sockaddr for us
745  * @param addrlen the len of addr
746  * @param force_address not used, we had better have an address to send to
747  *        because we are stateless!!
748  * @param cont continuation to call once the message has
749  *        been transmitted (or if the transport is ready
750  *        for the next transmission call; or if the
751  *        peer disconnected...)
752  * @param cont_cls closure for cont
753  *
754  * @return the number of bytes written (may return 0 and the message can
755  *         still be transmitted later!)
756  */
757 static ssize_t
758 udp_plugin_send (void *cls,
759                      const struct GNUNET_PeerIdentity *target,
760                      const char *msgbuf,
761                      size_t msgbuf_size,
762                      unsigned int priority,
763                      struct GNUNET_TIME_Relative timeout,
764                      struct Session *session,
765                      const void *addr,
766                      size_t addrlen,
767                      int force_address,
768                      GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
769 {
770   struct Plugin *plugin = cls;
771   ssize_t sent;
772   struct MessageQueue *temp_message;
773   struct PeerSession *peer_session;
774   int other_peer_natd;
775   const struct IPv4UdpAddress *t4;
776
777   if (force_address == GNUNET_SYSERR)
778     return GNUNET_SYSERR;
779   GNUNET_assert (NULL == session);
780
781   other_peer_natd = GNUNET_NO;
782   if (addrlen == sizeof(struct IPv4UdpAddress))
783     {
784       t4 = addr;
785       if (ntohs(t4->u_port) == 0)
786         other_peer_natd = GNUNET_YES;
787     }
788   else if (addrlen != sizeof(struct IPv6UdpAddress))
789     {
790       GNUNET_break_op(0);
791       return -1; /* Must have an address to send to */
792     }
793
794   sent = 0;
795   if ((other_peer_natd == GNUNET_YES) && (plugin->allow_nat == GNUNET_YES))
796     {
797       peer_session = find_session(plugin, target);
798       if (peer_session == NULL) /* We have a new peer to add */
799         {
800           /*
801            * The first time, we can assume we have no knowledge of a
802            * working port for this peer, call the ICMP/UDP message sender
803            * and wait...
804            */
805           peer_session = GNUNET_malloc(sizeof(struct PeerSession));
806           peer_session->connect_addr = GNUNET_malloc(addrlen);
807           memcpy(peer_session->connect_addr, addr, addrlen);
808           peer_session->connect_alen = addrlen;
809           peer_session->plugin = plugin;
810           peer_session->sock = NULL;
811           memcpy(&peer_session->target, target, sizeof(struct GNUNET_PeerIdentity));
812           peer_session->expecting_welcome = GNUNET_YES;
813
814           peer_session->next = plugin->sessions;
815           plugin->sessions = peer_session;
816
817           peer_session->messages = GNUNET_malloc(sizeof(struct MessageQueue));
818           peer_session->messages->msgbuf = GNUNET_malloc(msgbuf_size);
819           memcpy(peer_session->messages->msgbuf, msgbuf, msgbuf_size);
820           peer_session->messages->msgbuf_size = msgbuf_size;
821           peer_session->messages->timeout = GNUNET_TIME_relative_to_absolute(timeout);
822           peer_session->messages->cont = cont;
823           peer_session->messages->cont_cls = cont_cls;
824 #if DEBUG_UDP
825           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
826                           _("Other peer is NAT'd, set up peer session for peer %s\n"), GNUNET_i2s(target));
827 #endif
828           run_gnunet_nat_client(plugin, addr, addrlen);
829         }
830       else
831         {
832           if (peer_session->expecting_welcome == GNUNET_NO) /* We are "connected" */
833             {
834               sent = udp_real_send(cls,
835                                    peer_session->sock,
836                                    target,
837                                    msgbuf, msgbuf_size,
838                                    priority, timeout,
839                                    peer_session->connect_addr, peer_session->connect_alen,
840                                    cont, cont_cls);
841             }
842           else /* Haven't gotten a response from this peer, queue message */
843             {
844               temp_message = GNUNET_malloc(sizeof(struct MessageQueue));
845               temp_message->msgbuf = GNUNET_malloc(msgbuf_size);
846               memcpy(temp_message->msgbuf, msgbuf, msgbuf_size);
847               temp_message->msgbuf_size = msgbuf_size;
848               temp_message->timeout = GNUNET_TIME_relative_to_absolute(timeout);
849               temp_message->cont = cont;
850               temp_message->cont_cls = cont_cls;
851               temp_message->next = peer_session->messages;
852               peer_session->messages = temp_message;
853             }
854         }
855     }
856   else if (other_peer_natd == GNUNET_NO) /* Other peer not behind a NAT, so we can just send the message as is */
857     {
858       sent = udp_real_send(cls,
859                            (addrlen == sizeof (struct IPv4UdpAddress)) ? plugin->udp_sockv4.desc : plugin->udp_sockv6.desc,
860                            target,
861                            msgbuf, msgbuf_size,
862                            priority, timeout, addr, addrlen,
863                            cont, cont_cls);
864     }
865   else /* Other peer is NAT'd, but we don't want to play with them (or can't!) */
866     {
867       return GNUNET_SYSERR;
868     }
869
870   /* When GNUNET_SYSERR is returned from udp_real_send, we will still call
871    * the callback so must not return GNUNET_SYSERR!
872    * If we did, then transport context would get freed twice. */
873   if (sent == GNUNET_SYSERR)
874     return 0;
875   return sent;
876 }
877
878
879 static void
880 add_to_address_list (struct Plugin *plugin,
881                      const void *arg,
882                      size_t arg_size)
883 {
884   struct LocalAddrList *lal;
885
886   lal = plugin->lal_head;
887   while (NULL != lal)
888     {
889       if ( (lal->size == arg_size) &&
890            (0 == memcmp (&lal[1], arg, arg_size)) )
891         return;
892       lal = lal->next;
893     }
894   lal = GNUNET_malloc (sizeof (struct LocalAddrList) + arg_size);
895   lal->size = arg_size;
896   memcpy (&lal[1], arg, arg_size);
897   GNUNET_CONTAINER_DLL_insert (plugin->lal_head,
898                                plugin->lal_tail,
899                                lal);
900 }
901
902
903 static int
904 check_local_addr (struct Plugin *plugin,
905                   const void *arg,
906                   size_t arg_size)
907 {
908   struct LocalAddrList *lal;
909
910   lal = plugin->lal_head;
911   while (NULL != lal)
912     {
913       if ( (lal->size == arg_size) &&
914            (0 == memcmp (&lal[1], arg, arg_size)) )
915         return GNUNET_OK;
916       lal = lal->next;
917     }
918   return GNUNET_SYSERR;
919 }
920
921
922 /**
923  * Add the IP of our network interface to the list of
924  * our external IP addresses.
925  */
926 static int
927 process_interfaces (void *cls,
928                     const char *name,
929                     int isDefault,
930                     const struct sockaddr *addr, socklen_t addrlen)
931 {
932   struct Plugin *plugin = cls;
933   int af;
934   struct IPv4UdpAddress t4;
935   struct IPv6UdpAddress t6;
936   void *arg;
937   uint16_t args;
938   void *addr_nat;
939   char buf[INET6_ADDRSTRLEN];
940
941   addr_nat = NULL;
942   af = addr->sa_family;
943
944   memset(buf, 0, INET6_ADDRSTRLEN);
945   if (af == AF_INET)
946     {
947       t4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
948       GNUNET_assert(NULL != inet_ntop(AF_INET, &t4.ipv4_addr, &buf[0], INET_ADDRSTRLEN));
949       if ((plugin->bind6_address != NULL) || ((plugin->bind_address != NULL) && (0 != strcmp(buf, plugin->bind_address))))
950         {
951           GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: Not notifying transport of address %s\n", "UDP", GNUNET_a2s (addr, addrlen));
952           return GNUNET_OK;
953         }
954       add_to_address_list (plugin, &t4.ipv4_addr, sizeof (uint32_t));
955       if ((plugin->behind_nat == GNUNET_YES) && (plugin->only_nat_addresses == GNUNET_YES))
956         {
957           t4.u_port = htons (DEFAULT_NAT_PORT);
958         }
959       else if (plugin->behind_nat == GNUNET_YES) /* We are behind NAT, but will advertise NAT and normal addresses */
960         {
961           addr_nat = GNUNET_malloc(sizeof(t4));
962           t4.u_port = htons (DEFAULT_NAT_PORT);
963           memcpy(addr_nat, &t4, sizeof(t4));
964           t4.u_port = plugin->port;
965         }
966       else
967         {
968           t4.u_port = htons(plugin->port);
969         }
970       arg = &t4;
971       args = sizeof (t4);
972     }
973   else if (af == AF_INET6)
974     {
975       if (IN6_IS_ADDR_LINKLOCAL (&((struct sockaddr_in6 *) addr)->sin6_addr))
976         {
977           /* skip link local addresses */
978           return GNUNET_OK;
979         }
980       memcpy (&t6.ipv6_addr,
981               &((struct sockaddr_in6 *) addr)->sin6_addr,
982               sizeof (struct in6_addr));
983       GNUNET_assert(NULL != inet_ntop(AF_INET6, &t6.ipv6_addr, &buf[0], INET6_ADDRSTRLEN));
984       if (((plugin->bind_address != NULL) && (0 != strcmp(buf, plugin->bind_address)))
985           || ((plugin->bind6_address != NULL) && (0 != strcmp(buf, plugin->bind6_address))))
986         {
987           GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: Not notifying transport of address %s\n", "UDP", GNUNET_a2s (addr, addrlen));
988           return GNUNET_OK;
989         }
990       add_to_address_list (plugin, &t6.ipv6_addr, sizeof (struct in6_addr));
991       if ((plugin->behind_nat == GNUNET_YES) && (plugin->only_nat_addresses == GNUNET_YES))
992         {
993           t6.u6_port = htons (DEFAULT_NAT_PORT);
994         }
995       else if (plugin->behind_nat == GNUNET_YES)
996         {
997           addr_nat = GNUNET_malloc(sizeof(t6));
998           t6.u6_port = htons (DEFAULT_NAT_PORT);
999           memcpy(addr_nat, &t6, sizeof(t6));
1000           t6.u6_port = plugin->port;
1001         }
1002       else
1003         {
1004           t6.u6_port = htons (plugin->port);
1005         }
1006
1007       arg = &t6;
1008       args = sizeof (t6);
1009     }
1010   else
1011     {
1012       GNUNET_break (0);
1013       return GNUNET_OK;
1014     }
1015
1016   GNUNET_log (GNUNET_ERROR_TYPE_INFO |
1017               GNUNET_ERROR_TYPE_BULK,
1018               _("Found address `%s' (%s)\n"),
1019               GNUNET_a2s (addr, addrlen), name);
1020
1021   if (addr_nat != NULL)
1022     {
1023       plugin->env->notify_address (plugin->env->cls,
1024                                    "udp",
1025                                    addr_nat, args, GNUNET_TIME_UNIT_FOREVER_REL);
1026       GNUNET_log (GNUNET_ERROR_TYPE_INFO |
1027                   GNUNET_ERROR_TYPE_BULK,
1028                   _("Found NAT address `%s' (%s)\n"),
1029                   GNUNET_a2s (addr_nat, args), name);
1030       GNUNET_free(addr_nat);
1031     }
1032
1033   plugin->env->notify_address (plugin->env->cls,
1034                                "udp",
1035                                arg, args, GNUNET_TIME_UNIT_FOREVER_REL);
1036   return GNUNET_OK;
1037 }
1038
1039
1040 /**
1041  * Function called by the resolver for each address obtained from DNS
1042  * for our own hostname.  Add the addresses to the list of our
1043  * external IP addresses.
1044  *
1045  * @param cls closure
1046  * @param addr one of the addresses of the host, NULL for the last address
1047  * @param addrlen length of the address
1048  */
1049 static void
1050 process_hostname_ips (void *cls,
1051                       const struct sockaddr *addr, socklen_t addrlen)
1052 {
1053   struct Plugin *plugin = cls;
1054
1055   if (addr == NULL)
1056     {
1057       plugin->hostname_dns = NULL;
1058       return;
1059     }
1060   process_interfaces (plugin, "<hostname>", GNUNET_YES, addr, addrlen);
1061 }
1062
1063
1064 /**
1065  * Send UDP probe messages or UDP keepalive messages, depending on the
1066  * state of the connection.
1067  *
1068  * @param cls closure for this call (should be the main Plugin)
1069  * @param tc task context for running this
1070  */
1071 static void
1072 send_udp_probe_message (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1073 {
1074   struct UDP_NAT_Probes *probe = cls;
1075   struct UDP_NAT_ProbeMessage message;
1076   struct Plugin *plugin = probe->plugin;
1077
1078   memset (&message, 0, sizeof (message));
1079   message.header.size = htons(sizeof(struct UDP_NAT_ProbeMessage));
1080   message.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE);
1081   /* If they gave us a port, use that.  If not, try our port. */
1082   if (ntohs(probe->addr.u_port) == 0)
1083     probe->addr.u_port = htons(plugin->port);
1084
1085 #if DEBUG_UDP
1086       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1087                       _("Sending a probe to port %d\n"), ntohs(probe->addr.u_port));
1088 #endif
1089   probe->count++;
1090   udp_real_send(plugin,
1091                 plugin->udp_sockv4.desc,
1092                 NULL,
1093                 (char *)&message, ntohs(message.header.size), 0,
1094                 GNUNET_TIME_relative_get_unit(),
1095                 &probe->addr, sizeof(struct IPv4UdpAddress),
1096                 &udp_probe_continuation, probe);
1097 }
1098
1099
1100 /**
1101  * Continuation for probe sends.  If the last probe was sent
1102  * "successfully", schedule sending of another one.  If not,
1103  *
1104  */
1105 void
1106 udp_probe_continuation (void *cls, const struct GNUNET_PeerIdentity *target, int result)
1107 {
1108   struct UDP_NAT_Probes *probe = cls;
1109   /*struct Plugin *plugin = probe->plugin;*/
1110
1111   if ((result == GNUNET_OK) && (probe->count < MAX_PROBES))
1112     {
1113 #if DEBUG_UDP
1114       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1115                        _("Scheduling next probe for 10000 milliseconds\n"));
1116 #endif
1117       probe->task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 10000), &send_udp_probe_message, probe);
1118     }
1119   else /* Destroy the probe context. */
1120     {
1121 #if DEBUG_UDP
1122       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1123                       _("Sending probe didn't go well...\n"));
1124 #endif
1125     }
1126 }
1127
1128 /**
1129  * Find probe message by address
1130  *
1131  * @param plugin the plugin for this transport
1132  * @param address_string the ip address as a string
1133  */
1134 struct UDP_NAT_Probes *
1135 find_probe(struct Plugin *plugin, char * address_string)
1136 {
1137   struct UDP_NAT_Probes *pos;
1138
1139   pos = plugin->probes;
1140   while (pos != NULL)
1141     if (strcmp(pos->address_string, address_string) == 0)
1142       return pos;
1143
1144   return pos;
1145 }
1146
1147
1148 /*
1149  * @param cls the plugin handle
1150  * @param tc the scheduling context (for rescheduling this function again)
1151  *
1152  * We have been notified that gnunet-nat-server has written something to stdout.
1153  * Handle the output, then reschedule this function to be called again once
1154  * more is available.
1155  *
1156  */
1157 static void
1158 udp_plugin_server_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1159 {
1160   struct Plugin *plugin = cls;
1161   char mybuf[40];
1162   ssize_t bytes;
1163   memset(&mybuf, 0, sizeof(mybuf));
1164   int i;
1165   struct UDP_NAT_Probes *temp_probe;
1166   int port;
1167   char *port_start;
1168   struct IPv4UdpAddress a4;
1169
1170   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1171     return;
1172
1173   bytes = GNUNET_DISK_file_read(plugin->server_stdout_handle, &mybuf, sizeof(mybuf));
1174
1175   if (bytes < 1)
1176     {
1177 #if DEBUG_UDP
1178       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1179                       _("Finished reading from server stdout with code: %d\n"), bytes);
1180 #endif
1181       return;
1182     }
1183
1184   port_start = NULL;
1185   for (i = 0; i < sizeof(mybuf); i++)
1186     {
1187       if (mybuf[i] == '\n')
1188         mybuf[i] = '\0';
1189
1190       if ((mybuf[i] == ':') && (i + 1 < sizeof(mybuf)))
1191         {
1192           mybuf[i] = '\0';
1193           port_start = &mybuf[i + 1];
1194         }
1195     }
1196
1197   if (port_start != NULL)
1198     port = atoi(port_start);
1199   else
1200     {
1201       plugin->server_read_task =
1202            GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1203                                            plugin->server_stdout_handle, &udp_plugin_server_read, plugin);
1204       return;
1205     }
1206
1207 #if DEBUG_UDP
1208   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1209                   _("nat-server-read read: %s port %d\n"), &mybuf, port);
1210 #endif
1211
1212   /**
1213    * We have received an ICMP response, ostensibly from a non-NAT'd peer
1214    *  that wants to connect to us! Send a message to establish a connection.
1215    */
1216   if (inet_pton(AF_INET, &mybuf[0], &a4.ipv4_addr) != 1)
1217     {
1218
1219       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1220                   _("nat-server-read malformed address\n"), &mybuf, port);
1221
1222       plugin->server_read_task =
1223           GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1224                                           plugin->server_stdout_handle, &udp_plugin_server_read, plugin);
1225       return;
1226     }
1227
1228   temp_probe = find_probe(plugin, &mybuf[0]);
1229
1230   if (temp_probe == NULL)
1231     {
1232       temp_probe = GNUNET_malloc(sizeof(struct UDP_NAT_Probes));
1233       temp_probe->address_string = strdup(&mybuf[0]);
1234       GNUNET_assert (1 == inet_pton(AF_INET, &mybuf[0], &temp_probe->addr.ipv4_addr));
1235       temp_probe->addr.u_port = htons(port);
1236       temp_probe->next = plugin->probes;
1237       temp_probe->plugin = plugin;
1238       temp_probe->task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 500), &send_udp_probe_message, temp_probe);
1239       plugin->probes = temp_probe;
1240     }
1241
1242   plugin->server_read_task =
1243        GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1244                                        plugin->server_stdout_handle, &udp_plugin_server_read, plugin);
1245
1246 }
1247
1248
1249 /**
1250  * Demultiplexer for UDP NAT messages
1251  *
1252  * @param plugin the main plugin for this transport
1253  * @param sender from which peer the message was received
1254  * @param currhdr pointer to the header of the message
1255  * @param sender_addr the address from which the message was received
1256  * @param fromlen the length of the address
1257  * @param sockinfo which socket did we receive the message on
1258  */
1259 static void
1260 udp_demultiplexer(struct Plugin *plugin, 
1261                   struct GNUNET_PeerIdentity *sender,
1262                   const struct GNUNET_MessageHeader *currhdr,
1263                   const void *sender_addr,
1264                   size_t fromlen, struct UDP_Sock_Info *sockinfo)
1265 {
1266   struct UDP_NAT_ProbeMessageReply *outgoing_probe_reply;
1267   struct UDP_NAT_ProbeMessageConfirmation *outgoing_probe_confirmation;
1268   char addr_buf[INET_ADDRSTRLEN];
1269   struct UDP_NAT_Probes *outgoing_probe;
1270   struct PeerSession *peer_session;
1271   struct MessageQueue *pending_message;
1272   struct MessageQueue *pending_message_temp;
1273   uint16_t incoming_port;
1274
1275   if (memcmp(sender, plugin->env->my_identity, sizeof(struct GNUNET_PeerIdentity)) == 0)
1276     {
1277 #if DEBUG_UDP
1278       GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp",
1279                       _("Received a message from myself, dropping!!!\n"));
1280 #endif
1281       return;
1282     }
1283
1284   incoming_port = 0;
1285   GNUNET_assert(sender_addr != NULL); /* Can recvfrom have a NULL address? */
1286   if (fromlen == sizeof(struct IPv4UdpAddress))
1287     {
1288       incoming_port = ntohs(((struct IPv4UdpAddress *)sender_addr)->u_port);
1289     }
1290   else if (fromlen == sizeof(struct IPv6UdpAddress))
1291     {
1292       incoming_port = ntohs(((struct IPv6UdpAddress *)sender_addr)->u6_port);
1293     }
1294
1295   switch (ntohs(currhdr->type))
1296   {
1297     case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE:
1298       /* Send probe reply */
1299       outgoing_probe_reply = GNUNET_malloc(sizeof(struct UDP_NAT_ProbeMessageReply));
1300       outgoing_probe_reply->header.size = htons(sizeof(struct UDP_NAT_ProbeMessageReply));
1301       outgoing_probe_reply->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_REPLY);
1302
1303 #if DEBUG_UDP
1304       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1305                   _("Received a probe on listen port %d, sent_from port %d\n"),
1306                    sockinfo->port, incoming_port);
1307 #endif
1308
1309       udp_real_send(plugin, sockinfo->desc, NULL,
1310                     (char *)outgoing_probe_reply,
1311                     ntohs(outgoing_probe_reply->header.size), 0,
1312                     GNUNET_TIME_relative_get_unit(),
1313                     sender_addr, fromlen,
1314                     NULL, NULL);
1315
1316 #if DEBUG_UDP
1317       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1318                   _("Sent PROBE REPLY to port %d on outgoing port %d\n"),
1319                    incoming_port, sockinfo->port);
1320 #endif
1321       GNUNET_free(outgoing_probe_reply);
1322       break;
1323     case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_REPLY:
1324       /* Check for existing probe, check ports returned, send confirmation if all is well */
1325 #if DEBUG_UDP
1326       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1327                   _("Received PROBE REPLY from port %d on incoming port %d\n"), incoming_port, sockinfo->port);
1328 #endif
1329       if (fromlen == sizeof(struct IPv4UdpAddress))
1330         {
1331           memset(&addr_buf, 0, sizeof(addr_buf));
1332           if (NULL == inet_ntop (AF_INET,
1333                                  &((struct IPv4UdpAddress *) sender_addr)->ipv4_addr, addr_buf,
1334                                  INET_ADDRSTRLEN))
1335             {
1336               GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "inet_ntop");
1337               return;
1338             }
1339           outgoing_probe = find_probe(plugin, &addr_buf[0]);
1340           if (outgoing_probe != NULL)
1341             {
1342 #if DEBUG_UDP
1343               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1344                           _("Sending confirmation that we were reached!\n"));
1345 #endif
1346               outgoing_probe_confirmation = GNUNET_malloc(sizeof(struct UDP_NAT_ProbeMessageConfirmation));
1347               outgoing_probe_confirmation->header.size = htons(sizeof(struct UDP_NAT_ProbeMessageConfirmation));
1348               outgoing_probe_confirmation->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_CONFIRM);
1349               udp_real_send(plugin, sockinfo->desc, NULL,
1350                             (char *)outgoing_probe_confirmation,
1351                             ntohs(outgoing_probe_confirmation->header.size), 0,
1352                             GNUNET_TIME_relative_get_unit(),
1353                             sender_addr, fromlen, NULL, NULL);
1354
1355               if (outgoing_probe->task != GNUNET_SCHEDULER_NO_TASK)
1356                 {
1357                   GNUNET_SCHEDULER_cancel(outgoing_probe->task);
1358                   outgoing_probe->task = GNUNET_SCHEDULER_NO_TASK;
1359                   /* Schedule task to timeout and remove probe if confirmation not received */
1360                 }
1361               GNUNET_free(outgoing_probe_confirmation);
1362             }
1363           else
1364             {
1365 #if DEBUG_UDP
1366               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1367                           _("Received a probe reply, but have no record of a sent probe!\n"));
1368 #endif
1369             }
1370         }
1371       else
1372         {
1373 #if DEBUG_UDP
1374           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1375                       _("Received a probe reply, but sender address size is WRONG (should be %d, is %d)!\n"), sizeof(struct IPv4UdpAddress), fromlen);
1376 #endif
1377         }
1378       break;
1379     case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_CONFIRM:
1380       peer_session = find_session(plugin, sender);
1381 #if DEBUG_UDP
1382           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1383                       _("Looking up peer session for peer %s\n"), GNUNET_i2s(sender));
1384 #endif
1385       if (peer_session == NULL) /* Shouldn't this NOT happen? */
1386         {
1387 #if DEBUG_UDP
1388           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1389                       _("Peer not in list, adding (THIS MAY BE A MISTAKE) %s\n"), GNUNET_i2s(sender));
1390 #endif
1391           peer_session = GNUNET_malloc(sizeof(struct PeerSession));
1392           peer_session->connect_addr = GNUNET_malloc(fromlen);
1393           memcpy(peer_session->connect_addr, sender_addr, fromlen);
1394           peer_session->connect_alen = fromlen;
1395           peer_session->plugin = plugin;
1396           peer_session->sock = sockinfo->desc;
1397           memcpy(&peer_session->target, sender, sizeof(struct GNUNET_PeerIdentity));
1398           peer_session->expecting_welcome = GNUNET_NO;
1399
1400           peer_session->next = plugin->sessions;
1401           plugin->sessions = peer_session;
1402
1403           peer_session->messages = NULL;
1404         }
1405       else if (peer_session->expecting_welcome == GNUNET_YES)
1406         {
1407           peer_session->expecting_welcome = GNUNET_NO;
1408           peer_session->sock = sockinfo->desc;
1409           if (peer_session->connect_alen == sizeof(struct IPv4UdpAddress))
1410             {
1411               ((struct IPv4UdpAddress *)peer_session->connect_addr)->u_port = htons(incoming_port);
1412             }
1413           else if (peer_session->connect_alen == sizeof(struct IPv4UdpAddress))
1414             {
1415               ((struct IPv6UdpAddress *)peer_session->connect_addr)->u6_port = htons(incoming_port);
1416             }
1417
1418 #if DEBUG_UDP
1419               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1420                           _("Received a probe confirmation, will send to peer on port %d\n"), incoming_port);
1421 #endif
1422           if (peer_session->messages != NULL)
1423             {
1424 #if DEBUG_UDP
1425               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1426                           _("Received a probe confirmation, sending queued messages.\n"));
1427 #endif
1428               pending_message = peer_session->messages;
1429               int count = 0;
1430               while (pending_message != NULL)
1431                 {
1432 #if DEBUG_UDP
1433                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1434                               _("sending queued message %d\n"), count);
1435 #endif
1436                   udp_real_send(plugin,
1437                                 peer_session->sock,
1438                                 &peer_session->target,
1439                                 pending_message->msgbuf,
1440                                 pending_message->msgbuf_size, 0,
1441                                 GNUNET_TIME_relative_get_unit(),
1442                                 peer_session->connect_addr,
1443                                 peer_session->connect_alen,
1444                                 pending_message->cont,
1445                                 pending_message->cont_cls);
1446
1447                   pending_message_temp = pending_message;
1448                   pending_message = pending_message->next;
1449                   GNUNET_free(pending_message_temp->msgbuf);
1450                   GNUNET_free(pending_message_temp);
1451 #if DEBUG_UDP
1452                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1453                               _("finished sending queued message %d\n"), count);
1454 #endif
1455                   count++;
1456                 }
1457             }
1458
1459         }
1460       else
1461         {
1462 #if DEBUG_UDP
1463           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1464                       _("Received probe confirmation for already confirmed peer!\n"));
1465 #endif
1466         }
1467       /* Received confirmation, add peer with address/port specified */
1468       break;
1469     case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE_KEEPALIVE:
1470       /* Once we've sent NAT_PROBE_CONFIRM change to sending keepalives */
1471       /* If we receive these just ignore! */
1472       break;
1473     default:
1474 #if DEBUG_UDP
1475       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1476                   "Sending message type %d to transport!\n",
1477                   ntohs(currhdr->type));
1478 #endif
1479       struct GNUNET_TRANSPORT_ATS_Information distance[2];
1480       distance[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
1481       distance[0].value = htonl (UDP_DIRECT_DISTANCE);
1482       distance[1].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
1483       distance[1].value = htonl (0);
1484
1485       plugin->env->receive (plugin->env->cls, sender, currhdr,
1486                     (const struct GNUNET_TRANSPORT_ATS_Information *) &distance, 2,
1487                             NULL, sender_addr, fromlen);
1488   }
1489
1490 }
1491
1492
1493 /*
1494  * @param cls the plugin handle
1495  * @param tc the scheduling context (for rescheduling this function again)
1496  *
1497  * We have been notified that our writeset has something to read.  We don't
1498  * know which socket needs to be read, so we have to check each one
1499  * Then reschedule this function to be called again once more is available.
1500  *
1501  */
1502 static void
1503 udp_plugin_select (void *cls,
1504                    const struct GNUNET_SCHEDULER_TaskContext *tc)
1505 {
1506   struct Plugin *plugin = cls;
1507   char buf[65536];
1508   struct UDPMessage *msg;
1509   struct GNUNET_PeerIdentity sender;
1510   socklen_t fromlen;
1511   char addr[32];
1512   ssize_t ret;
1513   int offset;
1514   int tsize;
1515   char *msgbuf;
1516   const struct GNUNET_MessageHeader *currhdr;
1517   struct IPv4UdpAddress t4;
1518   struct IPv6UdpAddress t6;
1519   const struct sockaddr_in *s4;
1520   const struct sockaddr_in6 *s6;
1521   const void *ca;
1522   size_t calen;
1523   struct UDP_Sock_Info *udp_sock;
1524   uint16_t csize;
1525
1526   plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
1527   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1528     return;
1529   udp_sock = NULL;
1530   if (GNUNET_NETWORK_fdset_isset (tc->read_ready,
1531                                   plugin->udp_sockv4.desc))
1532     udp_sock = &plugin->udp_sockv4;
1533   else if (GNUNET_NETWORK_fdset_isset (tc->read_ready,
1534                                        plugin->udp_sockv6.desc))
1535     udp_sock = &plugin->udp_sockv6;
1536   if (NULL == udp_sock)
1537     {
1538       GNUNET_break (0);
1539       return;
1540     }
1541   fromlen = sizeof (addr);
1542   memset (&addr, 0, sizeof(addr));
1543   ret =
1544     GNUNET_NETWORK_socket_recvfrom (udp_sock->desc, buf, sizeof (buf),
1545                                     (struct sockaddr *)&addr, &fromlen);
1546
1547   if (AF_INET == ((struct sockaddr *)addr)->sa_family)
1548     {
1549       s4 = (const struct sockaddr_in*) &addr;
1550       t4.u_port = s4->sin_port;
1551       t4.ipv4_addr = s4->sin_addr.s_addr;
1552       ca = &t4;
1553       calen = sizeof (t4);
1554     }
1555   else if (AF_INET6 == ((struct sockaddr *)addr)->sa_family)
1556     {
1557       s6 = (const struct sockaddr_in6*) &addr;
1558       t6.u6_port = s6->sin6_port;
1559       memcpy (&t6.ipv6_addr,
1560               &s6->sin6_addr,
1561               sizeof (struct in6_addr));
1562       ca = &t6;
1563       calen = sizeof (t6);
1564     }
1565   else
1566     {
1567       GNUNET_break (0);
1568       ca = NULL;
1569       calen = 0;
1570     }
1571   if (ret < sizeof (struct UDPMessage))
1572     {
1573       GNUNET_break_op (0);
1574       plugin->select_task =
1575         GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1576                                      GNUNET_SCHEDULER_NO_TASK,
1577                                      GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
1578                                      NULL, &udp_plugin_select, plugin);
1579       return;
1580     }
1581   msg = (struct UDPMessage *) buf;
1582   csize = ntohs (msg->header.size);
1583   if ( (csize < sizeof (struct UDPMessage)) ||
1584        (csize > ret) )
1585     {
1586       GNUNET_break_op (0);
1587       plugin->select_task =
1588         GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1589                                      GNUNET_SCHEDULER_NO_TASK,
1590                                      GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
1591                                      NULL, &udp_plugin_select, plugin);
1592       return;
1593     }
1594   msgbuf = (char *)&msg[1];
1595   memcpy (&sender, &msg->sender, sizeof (struct GNUNET_PeerIdentity));
1596   offset = 0;
1597   tsize = csize - sizeof (struct UDPMessage);
1598   while (offset + sizeof (struct GNUNET_MessageHeader) <= tsize)
1599     {
1600       currhdr = (struct GNUNET_MessageHeader *)&msgbuf[offset];
1601       csize = ntohs (currhdr->size);
1602       if ( (csize < sizeof (struct GNUNET_MessageHeader)) ||
1603            (csize > tsize - offset) )
1604         {
1605           GNUNET_break_op (0);
1606           break;
1607         }
1608       udp_demultiplexer(plugin, &sender, currhdr, 
1609                         ca, calen, udp_sock);
1610       offset += csize;
1611     }
1612   plugin->select_task =
1613     GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1614                                  GNUNET_SCHEDULER_NO_TASK,
1615                                  GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
1616                                  NULL, &udp_plugin_select, plugin);
1617
1618 }
1619
1620 /**
1621  * Create a slew of UDP sockets.  If possible, use IPv6 and IPv4.
1622  *
1623  * @param cls closure for server start, should be a struct Plugin *
1624  * @return number of sockets created or GNUNET_SYSERR on error
1625 */
1626 static int
1627 udp_transport_server_start (void *cls)
1628 {
1629   struct Plugin *plugin = cls;
1630   struct sockaddr_in serverAddrv4;
1631   struct sockaddr_in6 serverAddrv6;
1632   struct sockaddr *serverAddr;
1633   socklen_t addrlen;
1634   int sockets_created;
1635   int tries;
1636
1637
1638   sockets_created = 0;
1639   if (plugin->behind_nat == GNUNET_YES)
1640     {
1641       /* Pipe to read from started processes stdout (on read end) */
1642       plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_NO, GNUNET_YES);
1643       if (plugin->server_stdout == NULL)
1644         return sockets_created;
1645 #if DEBUG_UDP
1646       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1647                   "Starting gnunet-nat-server process cmd: %s %s\n",
1648                   "gnunet-nat-server",
1649                   plugin->internal_address);
1650 #endif
1651       /* Start the server process */
1652       plugin->server_proc = GNUNET_OS_start_process(NULL,
1653                                                    plugin->server_stdout,
1654                                                    "gnunet-nat-server",
1655                                                    "gnunet-nat-server",
1656                                                    plugin->internal_address, NULL);
1657       if (plugin->server_proc == NULL)
1658         {
1659 #if DEBUG_UDP
1660           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1661                       "Failed to start gnunet-nat-server process\n");
1662 #endif
1663           return GNUNET_SYSERR;
1664         }
1665       /* Close the write end of the read pipe */
1666       GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
1667
1668       plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout, GNUNET_DISK_PIPE_END_READ);
1669       plugin->server_read_task =
1670         GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1671                                         plugin->server_stdout_handle, &udp_plugin_server_read, plugin);
1672     }
1673
1674   if ( (GNUNET_YES !=
1675         GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, "transport-udp",
1676                                               "DISABLEV6")))
1677     {
1678       plugin->udp_sockv6.desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 0);
1679       if (NULL == plugin->udp_sockv6.desc)
1680         {
1681           GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp", "socket");
1682         }
1683       else
1684         {
1685           memset (&serverAddrv6, 0, sizeof (serverAddrv6));
1686 #if HAVE_SOCKADDR_IN_SIN_LEN
1687           serverAddrv6.sin6_len = sizeof (serverAddrv6);
1688 #endif
1689
1690           serverAddrv6.sin6_family = AF_INET6;
1691           serverAddrv6.sin6_addr = in6addr_any;
1692           if (plugin->bind6_address != NULL)
1693             {
1694               if (1 != inet_pton(AF_INET6, plugin->bind6_address, &serverAddrv6.sin6_addr))
1695                 return 0;
1696             }
1697
1698           serverAddrv6.sin6_port = htons (plugin->port);
1699           addrlen = sizeof (serverAddrv6);
1700           serverAddr = (struct sockaddr *) &serverAddrv6;
1701 #if DEBUG_UDP
1702           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1703                            "Binding to IPv6 port %d\n",
1704                            ntohs(serverAddrv6.sin6_port));
1705 #endif
1706           tries = 0;
1707           while (GNUNET_NETWORK_socket_bind (plugin->udp_sockv6.desc, serverAddr, addrlen) !=
1708                  GNUNET_OK)
1709             {
1710               serverAddrv6.sin6_port = htons (GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a good, non-root port */
1711 #if DEBUG_UDP
1712               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1713                                "IPv6 Binding failed, trying new port %d\n",
1714                                ntohs(serverAddrv6.sin6_port));
1715 #endif
1716               tries++;
1717               if (tries > 10)
1718                 {
1719                   GNUNET_NETWORK_socket_close (plugin->udp_sockv6.desc);
1720                   plugin->udp_sockv6.desc = NULL;
1721                   break;
1722                 }       
1723             }
1724           if (plugin->udp_sockv6.desc != NULL)
1725             {
1726               plugin->udp_sockv6.port = ntohs(serverAddrv6.sin6_port);
1727               sockets_created++;
1728             }
1729         }
1730     }
1731
1732   plugin->udp_sockv4.desc = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 0);
1733   if (NULL == plugin->udp_sockv4.desc)
1734     {
1735       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "socket");
1736     }
1737   else
1738     {
1739       memset (&serverAddrv4, 0, sizeof (serverAddrv4));
1740 #if HAVE_SOCKADDR_IN_SIN_LEN
1741       serverAddrv4.sin_len = sizeof (serverAddrv4);
1742 #endif
1743       serverAddrv4.sin_family = AF_INET;
1744       serverAddrv4.sin_addr.s_addr = INADDR_ANY;
1745       if (plugin->bind_address != NULL)
1746         {
1747           if (1 != inet_pton(AF_INET, plugin->bind_address, &serverAddrv4.sin_addr))
1748             return 0;
1749         }
1750       serverAddrv4.sin_port = htons (plugin->port);
1751       addrlen = sizeof (serverAddrv4);
1752       serverAddr = (struct sockaddr *) &serverAddrv4;
1753 #if DEBUG_UDP
1754       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1755                        "Binding to IPv4 port %d\n",
1756                        ntohs(serverAddrv4.sin_port));
1757 #endif
1758       tries = 0;
1759       while (GNUNET_NETWORK_socket_bind (plugin->udp_sockv4.desc, serverAddr, addrlen) !=
1760              GNUNET_OK)
1761         {
1762           serverAddrv4.sin_port = htons (GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a good, non-root port */
1763 #if DEBUG_UDP
1764           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1765                            "IPv4 Binding failed, trying new port %d\n",
1766                            ntohs(serverAddrv4.sin_port));
1767 #endif
1768           tries++;
1769           if (tries > 10)
1770             {
1771               GNUNET_NETWORK_socket_close (plugin->udp_sockv4.desc);
1772               plugin->udp_sockv4.desc = NULL;
1773               break;
1774             }   
1775         }
1776       if (plugin->udp_sockv4.desc != NULL)
1777         {
1778           plugin->udp_sockv4.port = ntohs(serverAddrv4.sin_port);
1779           sockets_created++;
1780         }
1781     }
1782
1783   plugin->rs = GNUNET_NETWORK_fdset_create ();
1784   GNUNET_NETWORK_fdset_zero (plugin->rs);
1785   if (NULL != plugin->udp_sockv4.desc)
1786     GNUNET_NETWORK_fdset_set (plugin->rs,
1787                               plugin->udp_sockv4.desc);
1788   if (NULL != plugin->udp_sockv6.desc)
1789     GNUNET_NETWORK_fdset_set (plugin->rs,
1790                               plugin->udp_sockv6.desc);
1791
1792   plugin->select_task =
1793     GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1794                                  GNUNET_SCHEDULER_NO_TASK,
1795                                  GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
1796                                  NULL, &udp_plugin_select, plugin);
1797   return sockets_created;
1798 }
1799
1800
1801
1802 /**
1803  * Check if the given port is plausible (must be either
1804  * our listen port or our advertised port).  If it is
1805  * neither, we return GNUNET_SYSERR.
1806  *
1807  * @param plugin global variables
1808  * @param in_port port number to check
1809  * @return GNUNET_OK if port is either open_port or adv_port
1810  */
1811 static int
1812 check_port (struct Plugin *plugin, uint16_t in_port)
1813 {
1814   if ( (plugin->behind_nat == GNUNET_YES) && (in_port == 0) )
1815     return GNUNET_OK;
1816   if ( (plugin->only_nat_addresses == GNUNET_YES) &&
1817        (plugin->behind_nat == GNUNET_YES) )
1818     return GNUNET_SYSERR; /* odd case... */
1819   if (in_port == plugin->port)
1820     return GNUNET_OK;
1821   return GNUNET_SYSERR;
1822 }
1823
1824
1825 /**
1826  * Function that will be called to check if a binary address for this
1827  * plugin is well-formed and corresponds to an address for THIS peer
1828  * (as per our configuration).  Naturally, if absolutely necessary,
1829  * plugins can be a bit conservative in their answer, but in general
1830  * plugins should make sure that the address does not redirect
1831  * traffic to a 3rd party that might try to man-in-the-middle our
1832  * traffic.
1833  *
1834  * @param cls closure, should be our handle to the Plugin
1835  * @param addr pointer to the address
1836  * @param addrlen length of addr
1837  * @return GNUNET_OK if this is a plausible address for this peer
1838  *         and transport, GNUNET_SYSERR if not
1839  *
1840  */
1841 static int
1842 udp_check_address (void *cls,
1843                    const void *addr,
1844                    size_t addrlen)
1845 {
1846   struct Plugin *plugin = cls;
1847   char buf[INET6_ADDRSTRLEN];
1848   const void *sb;
1849   struct in_addr a4;
1850   struct in6_addr a6;
1851   int af;
1852   uint16_t port;
1853   struct IPv4UdpAddress *v4;
1854   struct IPv6UdpAddress *v6;
1855
1856   if ((addrlen != sizeof (struct IPv4UdpAddress)) &&
1857       (addrlen != sizeof (struct IPv6UdpAddress)))
1858     {
1859       GNUNET_break_op (0);
1860       return GNUNET_SYSERR;
1861     }
1862
1863   if (addrlen == sizeof (struct IPv4UdpAddress))
1864     {
1865       v4 = (struct IPv4UdpAddress *) addr;
1866       if (GNUNET_OK !=
1867           check_port (plugin, ntohs (v4->u_port)))
1868         return GNUNET_SYSERR;
1869       if (GNUNET_OK !=
1870           check_local_addr (plugin, &v4->ipv4_addr, sizeof (uint32_t)))
1871         return GNUNET_SYSERR;
1872
1873       af = AF_INET;
1874       port = ntohs (v4->u_port);
1875       memcpy (&a4, &v4->ipv4_addr, sizeof (a4));
1876       sb = &a4;
1877     }
1878   else
1879     {
1880       v6 = (struct IPv6UdpAddress *) addr;
1881       if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr))
1882         {
1883           GNUNET_break_op (0);
1884           return GNUNET_SYSERR;
1885         }
1886       if (GNUNET_OK !=
1887           check_port (plugin, ntohs (v6->u6_port)))
1888         return GNUNET_SYSERR;
1889       if (GNUNET_OK !=
1890           check_local_addr (plugin, &v6->ipv6_addr, sizeof (struct in6_addr)))
1891         return GNUNET_SYSERR;
1892
1893       af = AF_INET6;
1894       port = ntohs (v6->u6_port);
1895       memcpy (&a6, &v6->ipv6_addr, sizeof (a6));
1896       sb = &a6;
1897     }
1898
1899   inet_ntop (af, sb, buf, INET6_ADDRSTRLEN);
1900
1901 #if DEBUG_UDP
1902   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1903                    "Informing transport service about my address `%s:%u'\n",
1904                    buf,
1905                    port);
1906 #endif
1907   return GNUNET_OK;
1908 }
1909
1910
1911 /**
1912  * Append our port and forward the result.
1913  */
1914 static void
1915 append_port (void *cls, const char *hostname)
1916 {
1917   struct PrettyPrinterContext *ppc = cls;
1918   char *ret;
1919
1920   if (hostname == NULL)
1921     {
1922       ppc->asc (ppc->asc_cls, NULL);
1923       GNUNET_free (ppc);
1924       return;
1925     }
1926   GNUNET_asprintf (&ret, "%s:%d", hostname, ppc->port);
1927   ppc->asc (ppc->asc_cls, ret);
1928   GNUNET_free (ret);
1929 }
1930
1931
1932 /**
1933  * Convert the transports address to a nice, human-readable
1934  * format.
1935  *
1936  * @param cls closure
1937  * @param type name of the transport that generated the address
1938  * @param addr one of the addresses of the host, NULL for the last address
1939  *        the specific address format depends on the transport
1940  * @param addrlen length of the address
1941  * @param numeric should (IP) addresses be displayed in numeric form?
1942  * @param timeout after how long should we give up?
1943  * @param asc function to call on each string
1944  * @param asc_cls closure for asc
1945  */
1946 static void
1947 udp_plugin_address_pretty_printer (void *cls,
1948                                    const char *type,
1949                                    const void *addr,
1950                                    size_t addrlen,
1951                                    int numeric,
1952                                    struct GNUNET_TIME_Relative timeout,
1953                                    GNUNET_TRANSPORT_AddressStringCallback asc,
1954                                    void *asc_cls)
1955 {
1956   struct Plugin *plugin = cls;
1957   struct PrettyPrinterContext *ppc;
1958   const void *sb;
1959   size_t sbs;
1960   struct sockaddr_in a4;
1961   struct sockaddr_in6 a6;
1962   const struct IPv4UdpAddress *u4;
1963   const struct IPv6UdpAddress *u6;
1964   uint16_t port;
1965
1966   if (addrlen == sizeof (struct IPv6UdpAddress))
1967     {
1968       u6 = addr;
1969       memset (&a6, 0, sizeof (a6));
1970       a6.sin6_family = AF_INET6;
1971       a6.sin6_port = u6->u6_port;
1972       memcpy (&a6.sin6_addr,
1973               &u6->ipv6_addr,
1974               sizeof (struct in6_addr));
1975       port = ntohs (u6->u6_port);
1976       sb = &a6;
1977       sbs = sizeof (a6);
1978     }
1979   else if (addrlen == sizeof (struct IPv4UdpAddress))
1980     {
1981       u4 = addr;
1982       memset (&a4, 0, sizeof (a4));
1983       a4.sin_family = AF_INET;
1984       a4.sin_port = u4->u_port;
1985       a4.sin_addr.s_addr = u4->ipv4_addr;
1986       port = ntohs (u4->u_port);
1987       sb = &a4;
1988       sbs = sizeof (a4);
1989     }
1990   else
1991     {
1992       /* invalid address */
1993       GNUNET_break_op (0);
1994       asc (asc_cls, NULL);
1995       return;
1996     }
1997   ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext));
1998   ppc->asc = asc;
1999   ppc->asc_cls = asc_cls;
2000   ppc->port = port;
2001   GNUNET_RESOLVER_hostname_get (plugin->env->cfg,
2002                                 sb,
2003                                 sbs,
2004                                 !numeric, timeout, &append_port, ppc);
2005 }
2006
2007 /**
2008  * Return the actual path to a file found in the current
2009  * PATH environment variable.
2010  *
2011  * @param binary the name of the file to find
2012  */
2013 static char *
2014 get_path_from_PATH (char *binary)
2015 {
2016   char *path;
2017   char *pos;
2018   char *end;
2019   char *buf;
2020   const char *p;
2021
2022   p = getenv ("PATH");
2023   if (p == NULL)
2024     return NULL;
2025   path = GNUNET_strdup (p);     /* because we write on it */
2026   buf = GNUNET_malloc (strlen (path) + 20);
2027   pos = path;
2028
2029   while (NULL != (end = strchr (pos, PATH_SEPARATOR)))
2030     {
2031       *end = '\0';
2032       sprintf (buf, "%s/%s", pos, binary);
2033       if (GNUNET_DISK_file_test (buf) == GNUNET_YES)
2034         {
2035           GNUNET_free (path);
2036           return buf;
2037         }
2038       pos = end + 1;
2039     }
2040   sprintf (buf, "%s/%s", pos, binary);
2041   if (GNUNET_DISK_file_test (buf) == GNUNET_YES)
2042     {
2043       GNUNET_free (path);
2044       return buf;
2045     }
2046   GNUNET_free (buf);
2047   GNUNET_free (path);
2048   return NULL;
2049 }
2050
2051 /**
2052  * Check whether the suid bit is set on a file.
2053  * Attempts to find the file using the current
2054  * PATH environment variable as a search path.
2055  *
2056  * @param binary the name of the file to check
2057  */
2058 static int
2059 check_gnunet_nat_binary(char *binary)
2060 {
2061   struct stat statbuf;
2062   char *p;
2063 #ifdef MINGW
2064   SOCKET rawsock;
2065 #endif
2066
2067 #ifdef MINGW
2068   char *binaryexe;
2069   GNUNET_asprintf (&binaryexe, "%s.exe", binary);
2070   p = get_path_from_PATH (binaryexe);
2071   free (binaryexe);
2072 #else
2073   p = get_path_from_PATH (binary);
2074 #endif
2075   if (p == NULL)
2076     return GNUNET_NO;
2077   if (0 != STAT (p, &statbuf))
2078     {
2079       GNUNET_free (p);
2080       return GNUNET_SYSERR;
2081     }
2082   GNUNET_free (p);
2083 #ifndef MINGW
2084   if ( (0 != (statbuf.st_mode & S_ISUID)) &&
2085        (statbuf.st_uid == 0) )
2086     return GNUNET_YES;
2087   return GNUNET_NO;
2088 #else
2089   rawsock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
2090   if (INVALID_SOCKET == rawsock)
2091   {
2092     DWORD err = GetLastError ();
2093     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "socket (AF_INET, SOCK_RAW, IPPROTO_ICMP) have failed! GLE = %d\n", err);
2094     return GNUNET_NO; /* not running as administrator */
2095   }
2096   closesocket (rawsock);
2097   return GNUNET_YES;
2098 #endif
2099 }
2100
2101 /**
2102  * Function called for a quick conversion of the binary address to
2103  * a numeric address.  Note that the caller must not free the
2104  * address and that the next call to this function is allowed
2105  * to override the address again.
2106  *
2107  * @param cls closure
2108  * @param addr binary address
2109  * @param addrlen length of the address
2110  * @return string representing the same address
2111  */
2112 static const char*
2113 udp_address_to_string (void *cls,
2114                        const void *addr,
2115                        size_t addrlen)
2116 {
2117   static char rbuf[INET6_ADDRSTRLEN + 10];
2118   char buf[INET6_ADDRSTRLEN];
2119   const void *sb;
2120   struct in_addr a4;
2121   struct in6_addr a6;
2122   const struct IPv4UdpAddress *t4;
2123   const struct IPv6UdpAddress *t6;
2124   int af;
2125   uint16_t port;
2126
2127   if (addrlen == sizeof (struct IPv6UdpAddress))
2128     {
2129       t6 = addr;
2130       af = AF_INET6;
2131       port = ntohs (t6->u6_port);
2132       memcpy (&a6, &t6->ipv6_addr, sizeof (a6));
2133       sb = &a6;
2134     }
2135   else if (addrlen == sizeof (struct IPv4UdpAddress))
2136     {
2137       t4 = addr;
2138       af = AF_INET;
2139       port = ntohs (t4->u_port);
2140       memcpy (&a4, &t4->ipv4_addr, sizeof (a4));
2141       sb = &a4;
2142     }
2143   else
2144     return NULL;
2145   inet_ntop (af, sb, buf, INET6_ADDRSTRLEN);
2146   GNUNET_snprintf (rbuf,
2147                    sizeof (rbuf),
2148                    "%s:%u",
2149                    buf,
2150                    port);
2151   return rbuf;
2152 }
2153
2154 /**
2155  * The exported method. Makes the core api available via a global and
2156  * returns the udp transport API.
2157  */
2158 void *
2159 libgnunet_plugin_transport_udp_init (void *cls)
2160 {
2161   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
2162   unsigned long long mtu;
2163   unsigned long long port;
2164   struct GNUNET_TRANSPORT_PluginFunctions *api;
2165   struct Plugin *plugin;
2166   int sockets_created;
2167   int behind_nat;
2168   int allow_nat;
2169   int only_nat_addresses;
2170   char *internal_address;
2171   char *external_address;
2172   struct IPv4UdpAddress v4_address;
2173
2174   if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
2175                                                          "transport-udp",
2176                                                          "BEHIND_NAT"))
2177     {
2178       /* We are behind nat (according to the user) */
2179       if (check_gnunet_nat_binary("gnunet-nat-server") == GNUNET_YES)
2180         behind_nat = GNUNET_YES;
2181       else
2182         {
2183           behind_nat = GNUNET_NO;
2184           GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Configuration specified you are behind a NAT, but gnunet-nat-server is not installed properly (suid bit not set)!\n");
2185         }
2186     }
2187   else
2188     behind_nat = GNUNET_NO; /* We are not behind nat! */
2189
2190   if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
2191                                                          "transport-udp",
2192                                                          "ALLOW_NAT"))
2193     {
2194       if (check_gnunet_nat_binary("gnunet-nat-client") == GNUNET_YES)
2195         allow_nat = GNUNET_YES; /* We will try to connect to NAT'd peers */
2196       else
2197       {
2198         allow_nat = GNUNET_NO;
2199         GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Configuration specified you want to connect to NAT'd peers, but gnunet-nat-client is not installed properly (suid bit not set)!\n");
2200       }
2201
2202     }
2203   else
2204     allow_nat = GNUNET_NO; /* We don't want to try to help NAT'd peers */
2205
2206   if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
2207                                                            "transport-udp",
2208                                                            "ONLY_NAT_ADDRESSES"))
2209     only_nat_addresses = GNUNET_YES; /* We will only report our addresses as NAT'd */
2210   else
2211     only_nat_addresses = GNUNET_NO; /* We will report our addresses as NAT'd and non-NAT'd */
2212
2213   external_address = NULL;
2214   if (((GNUNET_YES == behind_nat) || (GNUNET_YES == allow_nat)) && (GNUNET_OK !=
2215          GNUNET_CONFIGURATION_get_value_string (env->cfg,
2216                                                 "transport-udp",
2217                                                 "EXTERNAL_ADDRESS",
2218                                                 &external_address)))
2219     {
2220       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2221                   _("Require EXTERNAL_ADDRESS for service `%s' in configuration (either BEHIND_NAT or ALLOW_NAT set to YES)!\n"),
2222                   "transport-udp");
2223       return NULL;
2224     }
2225
2226   if ((external_address != NULL) && (inet_pton(AF_INET, external_address, &v4_address.ipv4_addr) != 1))
2227     {
2228       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Malformed EXTERNAL_ADDRESS %s given in configuration!\n", external_address);
2229     }
2230
2231   internal_address = NULL;
2232   if ((GNUNET_YES == behind_nat) && (GNUNET_OK !=
2233          GNUNET_CONFIGURATION_get_value_string (env->cfg,
2234                                                 "transport-udp",
2235                                                 "INTERNAL_ADDRESS",
2236                                                 &internal_address)))
2237     {
2238       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2239                        _("Require INTERNAL_ADDRESS for service `%s' in configuration!\n"),
2240                        "transport-udp");
2241       GNUNET_free_non_null(external_address);
2242       return NULL;
2243     }
2244
2245   if ((internal_address != NULL) && (inet_pton(AF_INET, internal_address, &v4_address.ipv4_addr) != 1))
2246     {
2247       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Malformed INTERNAL_ADDRESS %s given in configuration!\n", internal_address);
2248     }
2249
2250   if (GNUNET_OK !=
2251       GNUNET_CONFIGURATION_get_value_number (env->cfg,
2252                                              "transport-udp",
2253                                              "PORT",
2254                                              &port))
2255     port = UDP_NAT_DEFAULT_PORT;
2256   else if (port > 65535)
2257     {
2258       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2259                   _("Given `%s' option is out of range: %llu > %u\n"),
2260                   "PORT",
2261                   port,
2262                   65535);
2263       GNUNET_free_non_null(external_address);
2264       GNUNET_free_non_null(internal_address);
2265       return NULL;
2266     }
2267
2268   mtu = 1240;
2269   if (mtu < 1200)
2270     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2271                 _("MTU %llu for `%s' is probably too low!\n"), mtu,
2272                 "UDP");
2273
2274   plugin = GNUNET_malloc (sizeof (struct Plugin));
2275   plugin->external_address = external_address;
2276   plugin->internal_address = internal_address;
2277   plugin->port = port;
2278   plugin->behind_nat = behind_nat;
2279   plugin->allow_nat = allow_nat;
2280   plugin->only_nat_addresses = only_nat_addresses;
2281   plugin->env = env;
2282
2283   api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
2284   api->cls = plugin;
2285
2286   api->send = &udp_plugin_send;
2287   api->disconnect = &udp_disconnect;
2288   api->address_pretty_printer = &udp_plugin_address_pretty_printer;
2289   api->address_to_string = &udp_address_to_string;
2290   api->check_address = &udp_check_address;
2291
2292   if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string(env->cfg, "transport-udp", "BINDTO", &plugin->bind_address))
2293     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Binding udp plugin to specific address: `%s'\n", plugin->bind_address);
2294   if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string(env->cfg, "transport-udp", "BINDTO6", &plugin->bind6_address))
2295     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Binding udp plugin to specific address: `%s'\n", plugin->bind6_address);
2296
2297   if (plugin->behind_nat == GNUNET_NO)
2298     {
2299       GNUNET_OS_network_interfaces_list (&process_interfaces, plugin);
2300     }
2301
2302   plugin->hostname_dns = GNUNET_RESOLVER_hostname_resolve (env->cfg,
2303                                                            AF_UNSPEC,
2304                                                            HOSTNAME_RESOLVE_TIMEOUT,
2305                                                            &process_hostname_ips,
2306                                                            plugin);
2307
2308   if ((plugin->behind_nat == GNUNET_YES) && (inet_pton(AF_INET, plugin->external_address, &v4_address.ipv4_addr) == 1))
2309     {
2310       v4_address.u_port = htons(0);
2311       plugin->env->notify_address (plugin->env->cls,
2312                                   "udp",
2313                                   &v4_address, sizeof(v4_address), GNUNET_TIME_UNIT_FOREVER_REL);
2314       add_to_address_list (plugin, &v4_address.ipv4_addr, sizeof (uint32_t));
2315       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Notifying plugin of address %s:0\n", plugin->external_address);
2316     }
2317   else if ((plugin->external_address != NULL) && (inet_pton(AF_INET, plugin->external_address, &v4_address.ipv4_addr) == 1))
2318     {
2319       v4_address.u_port = htons(plugin->port);
2320       plugin->env->notify_address (plugin->env->cls,
2321                                   "udp",
2322                                   &v4_address, sizeof(v4_address), GNUNET_TIME_UNIT_FOREVER_REL);
2323       add_to_address_list (plugin, &v4_address.ipv4_addr, sizeof (uint32_t));
2324     }
2325
2326   sockets_created = udp_transport_server_start (plugin);
2327   if (sockets_created == 0)
2328     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2329                 _("Failed to open UDP sockets\n"));
2330   return api;
2331 }
2332
2333 void *
2334 libgnunet_plugin_transport_udp_done (void *cls)
2335 {
2336   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
2337   struct Plugin *plugin = api->cls;
2338   struct LocalAddrList *lal;
2339
2340   udp_transport_server_stop (plugin);
2341   if (NULL != plugin->hostname_dns)
2342     {
2343       GNUNET_RESOLVER_request_cancel (plugin->hostname_dns);
2344       plugin->hostname_dns = NULL;
2345     }
2346
2347   GNUNET_NETWORK_fdset_destroy (plugin->rs);
2348   while (NULL != (lal = plugin->lal_head))
2349     {
2350       GNUNET_CONTAINER_DLL_remove (plugin->lal_head,
2351                                    plugin->lal_tail,
2352                                    lal);
2353       GNUNET_free (lal);
2354     }
2355   GNUNET_free (plugin);
2356   GNUNET_free (api);
2357   return NULL;
2358 }
2359
2360 /* end of plugin_transport_udp.c */