udp now supports broadcasts using ipv6 multicast
[oweals/gnunet.git] / src / transport / plugin_transport_udp.c
1 /*
2      This file is part of GNUnet
3      (C) 2010, 2011 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 #include "platform.h"
29 #include "gnunet_hello_lib.h"
30 #include "gnunet_util_lib.h"
31 #include "gnunet_fragmentation_lib.h"
32 #include "gnunet_nat_lib.h"
33 #include "gnunet_protocols.h"
34 #include "gnunet_resolver_service.h"
35 #include "gnunet_signatures.h"
36 #include "gnunet_constants.h"
37 #include "gnunet_statistics_service.h"
38 #include "gnunet_transport_service.h"
39 #include "gnunet_transport_plugin.h"
40 #include "transport.h"
41
42 #define LOG(kind,...) GNUNET_log_from (kind, "transport-udp", __VA_ARGS__)
43
44
45 #define DEBUG_UDP GNUNET_EXTRA_LOGGING
46
47 /**
48  * MTU for fragmentation subsystem.  Should be conservative since
49  * all communicating peers MUST work with this MTU.
50  */
51 #define UDP_MTU 1400
52
53 /**
54  * Number of messages we can defragment in parallel.  We only really
55  * defragment 1 message at a time, but if messages get re-ordered, we
56  * may want to keep knowledge about the previous message to avoid
57  * discarding the current message in favor of a single fragment of a
58  * previous message.  3 should be good since we don't expect massive
59  * message reorderings with UDP.
60  */
61 #define UDP_MAX_MESSAGES_IN_DEFRAG 3
62
63 /**
64  * We keep a defragmentation queue per sender address.  How many
65  * sender addresses do we support at the same time? Memory consumption
66  * is roughly a factor of 32k * UDP_MAX_MESSAGES_IN_DEFRAG times this
67  * value. (So 128 corresponds to 12 MB and should suffice for
68  * connecting to roughly 128 peers via UDP).
69  */
70 #define UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG 128
71
72
73 /**
74  * UDP Message-Packet header (after defragmentation).
75  */
76 struct UDPMessage
77 {
78   /**
79    * Message header.
80    */
81   struct GNUNET_MessageHeader header;
82
83   /**
84    * Always zero for now.
85    */
86   uint32_t reserved;
87
88   /**
89    * What is the identity of the sender
90    */
91   struct GNUNET_PeerIdentity sender;
92
93 };
94
95
96 /**
97  * UDP ACK Message-Packet header (after defragmentation).
98  */
99 struct UDP_ACK_Message
100 {
101   /**
102    * Message header.
103    */
104   struct GNUNET_MessageHeader header;
105
106   /**
107    * Desired delay for flow control
108    */
109   uint32_t delay;
110
111   /**
112    * What is the identity of the sender
113    */
114   struct GNUNET_PeerIdentity sender;
115 };
116
117
118 struct UDP_Beacon_Message
119 {
120  /**
121   * Message header.
122   */
123   struct GNUNET_MessageHeader header;
124
125  /**
126   * What is the identity of the sender
127   */
128   struct GNUNET_PeerIdentity sender;
129 };
130
131
132 /**
133  * Network format for IPv4 addresses.
134  */
135 struct IPv4UdpAddress
136 {
137   /**
138    * IPv4 address, in network byte order.
139    */
140   uint32_t ipv4_addr GNUNET_PACKED;
141
142   /**
143    * Port number, in network byte order.
144    */
145   uint16_t u4_port GNUNET_PACKED;
146 };
147
148
149 /**
150  * Network format for IPv6 addresses.
151  */
152 struct IPv6UdpAddress
153 {
154
155   /**
156    * IPv6 address.
157    */
158   struct in6_addr ipv6_addr GNUNET_PACKED;
159
160   /**
161    * Port number, in network byte order.
162    */
163   uint16_t u6_port GNUNET_PACKED;
164 };
165
166
167 /* Forward definition */
168 struct Plugin;
169
170
171 /**
172  * Session with another peer.  FIXME: why not make this into
173  * a regular 'struct Session' and pass it around!?
174  */
175 struct Session
176 {
177
178   /**
179    * Which peer is this session for?
180    */
181   struct GNUNET_PeerIdentity target;
182
183   /**
184    * Pointer to the global plugin struct.
185    */
186   struct Plugin *plugin;
187
188   /**
189    * Address of the other peer
190    */
191   const struct sockaddr *sock_addr;
192
193   size_t addrlen;
194
195   /**
196    * Function to call upon completion of the transmission.
197    */
198   GNUNET_TRANSPORT_TransmitContinuation cont;
199
200   /**
201    * Closure for 'cont'.
202    */
203   void *cont_cls;
204
205   /**
206    * Current outgoing message to this peer.
207    */
208   struct GNUNET_FRAGMENT_Context *frag;
209
210   struct GNUNET_TIME_Absolute valid_until;
211
212   GNUNET_SCHEDULER_TaskIdentifier invalidation_task;
213
214   GNUNET_SCHEDULER_TaskIdentifier delayed_cont_task;
215
216   /**
217    * Desired delay for next sending we send to other peer
218    */
219   struct GNUNET_TIME_Relative flow_delay_for_other_peer;
220
221   /**
222    * Desired delay for next sending we received from other peer
223    */
224   struct GNUNET_TIME_Absolute flow_delay_from_other_peer;
225 };
226
227
228 /**
229  * Data structure to track defragmentation contexts based
230  * on the source of the UDP traffic.
231  */
232 struct ReceiveContext
233 {
234
235   /**
236    * Defragmentation context.
237    */
238   struct GNUNET_DEFRAGMENT_Context *defrag;
239
240   /**
241    * Source address this receive context is for (allocated at the
242    * end of the struct).
243    */
244   const struct sockaddr *src_addr;
245
246   /**
247    * Reference to master plugin struct.
248    */
249   struct Plugin *plugin;
250
251   /**
252    * Node in the defrag heap.
253    */
254   struct GNUNET_CONTAINER_HeapNode *hnode;
255
256   /**
257    * Length of 'src_addr'
258    */
259   size_t addr_len;
260
261   struct GNUNET_PeerIdentity id;
262
263 };
264
265 struct BroadcastAddress
266 {
267   struct BroadcastAddress *next;
268   struct BroadcastAddress *prev;
269
270   void * addr;
271   socklen_t addrlen;
272 };
273
274
275 /**
276  * Encapsulation of all of the state of the plugin.
277  */
278 struct Plugin
279 {
280
281   /**
282    * Our environment.
283    */
284   struct GNUNET_TRANSPORT_PluginEnvironment *env;
285
286   /**
287    * Session of peers with whom we are currently connected,
288    * map of peer identity to 'struct PeerSession'.
289    */
290   struct GNUNET_CONTAINER_MultiHashMap *sessions;
291
292   /**
293    * Session of peers with whom we are currently connected,
294    * map of peer identity to 'struct PeerSession'.
295    */
296   struct GNUNET_CONTAINER_MultiHashMap *inbound_sessions;
297
298   /**
299    * Heap with all of our defragmentation activities.
300    */
301   struct GNUNET_CONTAINER_Heap *defrags;
302
303   /**
304    * ID of select task
305    */
306   GNUNET_SCHEDULER_TaskIdentifier select_task;
307
308   /**
309    * Tokenizer for inbound messages.
310    */
311   struct GNUNET_SERVER_MessageStreamTokenizer *mst;
312
313   /**
314    * Bandwidth tracker to limit global UDP traffic.
315    */
316   struct GNUNET_BANDWIDTH_Tracker tracker;
317
318   /**
319    * Address we were told to bind to exclusively (IPv4).
320    */
321   char *bind4_address;
322
323   /**
324    * Address we were told to bind to exclusively (IPv6).
325    */
326   char *bind6_address;
327
328   /**
329    * Handle to NAT traversal support.
330    */
331   struct GNUNET_NAT_Handle *nat;
332
333   /**
334    * FD Read set
335    */
336   struct GNUNET_NETWORK_FDSet *rs;
337
338   /**
339    * The read socket for IPv4
340    */
341   struct GNUNET_NETWORK_Handle *sockv4;
342
343   /**
344    * The read socket for IPv6
345    */
346   struct GNUNET_NETWORK_Handle *sockv6;
347
348   /**
349    * Beacon broadcasting
350    * -------------------
351    */
352
353   /**
354    * Broadcast interval
355    */
356   struct GNUNET_TIME_Relative broadcast_interval;
357
358   /**
359    * Broadcast with IPv4
360    */
361   int broadcast_ipv4;
362
363   /**
364    * Tokenizer for inbound messages.
365    */
366   struct GNUNET_SERVER_MessageStreamTokenizer *broadcast_ipv4_mst;
367
368   /**
369    * The read socket for IPv4
370    */
371   struct GNUNET_NETWORK_Handle *sockv4_broadcast;
372
373   struct BroadcastAddress *tail;
374   struct BroadcastAddress *head;
375
376   /**
377    * ID of select broadcast task
378    */
379   GNUNET_SCHEDULER_TaskIdentifier select_ipv4_broadcast_task;
380
381   /**
382    * ID of select broadcast task
383    */
384   GNUNET_SCHEDULER_TaskIdentifier send_ipv4_broadcast_task;
385
386   /**
387    * FD Read set
388    */
389   struct GNUNET_NETWORK_FDSet *broadcast_ipv4_rs;
390
391
392   /**
393    * Broadcast with IPv6
394    */
395   int broadcast_ipv6;
396
397
398   /**
399    * Tokenizer for inbound messages.
400    */
401   struct GNUNET_SERVER_MessageStreamTokenizer *broadcast_ipv6_mst;
402
403   /**
404    * The read socket for IPv6
405    */
406   struct GNUNET_NETWORK_Handle *sockv6_broadcast;
407
408
409   /**
410    * ID of select broadcast task
411    */
412   GNUNET_SCHEDULER_TaskIdentifier select_ipv6_broadcast_task;
413
414   /**
415    * ID of select broadcast task
416    */
417   GNUNET_SCHEDULER_TaskIdentifier send_ipv6_broadcast_task;
418
419
420   /**
421    * FD Read set
422    */
423   struct GNUNET_NETWORK_FDSet *broadcast_ipv6_rs;
424
425   /**
426    * IPv6 multicast address
427    */
428   struct sockaddr_in6 ipv6_multicast_address;
429
430
431   /**
432    * expected delay for ACKs
433    */
434   struct GNUNET_TIME_Relative last_expected_delay;
435
436   /**
437    * Port we broadcasting on.
438    */
439   uint16_t broadcast_port;
440
441   /**
442    * Port we listen on.
443    */
444   uint16_t port;
445
446   /**
447    * Port we advertise on.
448    */
449   uint16_t aport;
450
451 };
452
453 struct PeerSessionIteratorContext
454 {
455   struct Session *result;
456   const void *addr;
457   size_t addrlen;
458 };
459
460
461 /**
462  * Lookup the session for the given peer.
463  *
464  * @param plugin the plugin
465  * @param peer peer's identity
466  * @return NULL if we have no session
467  */
468 static struct Session *
469 find_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *peer)
470 {
471   return GNUNET_CONTAINER_multihashmap_get (plugin->sessions,
472                                             &peer->hashPubKey);
473 }
474
475
476 static int
477 inbound_session_iterator (void *cls, const GNUNET_HashCode * key, void *value)
478 {
479   struct PeerSessionIteratorContext *psc = cls;
480   struct Session *s = value;
481
482   if (s->addrlen == psc->addrlen)
483   {
484     if (0 == memcmp (&s[1], psc->addr, s->addrlen))
485       psc->result = s;
486   }
487   if (psc->result != NULL)
488     return GNUNET_NO;
489   return GNUNET_YES;
490 }
491
492
493 /**
494  * Lookup the session for the given peer.
495  *
496  * @param plugin the plugin
497  * @param peer peer's identity
498  * @return NULL if we have no session
499  */
500 static struct Session *
501 find_inbound_session (struct Plugin *plugin,
502                       const struct GNUNET_PeerIdentity *peer, const void *addr,
503                       size_t addrlen)
504 {
505   struct PeerSessionIteratorContext psc;
506
507   psc.result = NULL;
508   psc.addrlen = addrlen;
509   psc.addr = addr;
510
511   GNUNET_CONTAINER_multihashmap_get_multiple (plugin->inbound_sessions,
512                                               &peer->hashPubKey,
513                                               &inbound_session_iterator, &psc);
514   return psc.result;
515 }
516
517
518 static int
519 inbound_session_by_addr_iterator (void *cls, const GNUNET_HashCode * key,
520                                   void *value)
521 {
522   struct PeerSessionIteratorContext *psc = cls;
523   struct Session *s = value;
524
525   if (s->addrlen == psc->addrlen)
526   {
527     if (0 == memcmp (&s[1], psc->addr, s->addrlen))
528       psc->result = s;
529   }
530   if (psc->result != NULL)
531     return GNUNET_NO;
532   else
533     return GNUNET_YES;
534 };
535
536 /**
537  * Lookup the session for the given peer just by address.
538  *
539  * @param plugin the plugin
540  * @param addr address
541  * @param addrlen address length
542  * @return NULL if we have no session
543  */
544 static struct Session *
545 find_inbound_session_by_addr (struct Plugin *plugin, const void *addr,
546                               size_t addrlen)
547 {
548   struct PeerSessionIteratorContext psc;
549
550   psc.result = NULL;
551   psc.addrlen = addrlen;
552   psc.addr = addr;
553
554   GNUNET_CONTAINER_multihashmap_iterate (plugin->inbound_sessions,
555                                          &inbound_session_by_addr_iterator,
556                                          &psc);
557   return psc.result;
558 }
559
560
561 /**
562  * Destroy a session, plugin is being unloaded.
563  *
564  * @param cls unused
565  * @param key hash of public key of target peer
566  * @param value a 'struct PeerSession*' to clean up
567  * @return GNUNET_OK (continue to iterate)
568  */
569 static int
570 destroy_session (void *cls, const GNUNET_HashCode * key, void *value)
571 {
572   struct Session *peer_session = value;
573
574   GNUNET_assert (GNUNET_YES ==
575                  GNUNET_CONTAINER_multihashmap_remove (peer_session->plugin->sessions, 
576                                                        &peer_session->target.hashPubKey, peer_session));
577   if (peer_session->frag != NULL)
578     GNUNET_FRAGMENT_context_destroy (peer_session->frag);
579   if (GNUNET_SCHEDULER_NO_TASK != peer_session->delayed_cont_task)
580     GNUNET_SCHEDULER_cancel (peer_session->delayed_cont_task);
581   GNUNET_free (peer_session);
582   return GNUNET_OK;
583 }
584
585
586 /**
587  * Destroy a session, plugin is being unloaded.
588  *
589  * @param cls unused
590  * @param key hash of public key of target peer
591  * @param value a 'struct PeerSession*' to clean up
592  * @return GNUNET_OK (continue to iterate)
593  */
594 static int
595 destroy_inbound_session (void *cls, const GNUNET_HashCode * key, void *value)
596 {
597   struct Session *s = value;
598
599   if (s->invalidation_task != GNUNET_SCHEDULER_NO_TASK)
600     GNUNET_SCHEDULER_cancel (s->invalidation_task);
601   if (GNUNET_SCHEDULER_NO_TASK != s->delayed_cont_task)
602     GNUNET_SCHEDULER_cancel (s->delayed_cont_task);
603   GNUNET_CONTAINER_multihashmap_remove (s->plugin->inbound_sessions, &s->target.hashPubKey, s);
604   GNUNET_free (s);
605   return GNUNET_OK;
606 }
607
608
609 /**
610  * Disconnect from a remote node.  Clean up session if we have one for this peer
611  *
612  * @param cls closure for this call (should be handle to Plugin)
613  * @param target the peeridentity of the peer to disconnect
614  * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
615  */
616 static void
617 udp_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
618 {
619   struct Plugin *plugin = cls;
620   struct Session *session;
621
622   session = find_session (plugin, target);
623   if (NULL == session)
624     return;
625   GNUNET_assert (GNUNET_OK ==
626                  GNUNET_CONTAINER_multihashmap_remove (plugin->sessions,
627                                                        &target->hashPubKey,
628                                                        session));
629
630   GNUNET_CONTAINER_multihashmap_get_multiple (plugin->inbound_sessions,
631                                               &target->hashPubKey,
632                                               &destroy_inbound_session, NULL);
633   plugin->last_expected_delay = GNUNET_FRAGMENT_context_destroy (session->frag);
634   if (GNUNET_SCHEDULER_NO_TASK != session->delayed_cont_task)
635     GNUNET_SCHEDULER_cancel (session->delayed_cont_task);
636   if (session->cont != NULL)
637     session->cont (session->cont_cls, target, GNUNET_SYSERR);
638   GNUNET_free (session);
639 }
640
641
642 /**
643  * Actually send out the message.
644  *
645  * @param plugin the plugin
646  * @param sa the address to send the message to
647  * @param msg message to transmit
648  * @return the number of bytes written
649  */
650 static ssize_t
651 udp_send (struct Plugin *plugin, const struct sockaddr *sa,
652           const struct GNUNET_MessageHeader *msg)
653 {
654   ssize_t sent;
655   size_t slen;
656
657   switch (sa->sa_family)
658   {
659   case AF_INET:
660     if (NULL == plugin->sockv4)
661       return 0;
662     sent =
663         GNUNET_NETWORK_socket_sendto (plugin->sockv4, msg, ntohs (msg->size),
664                                       sa, slen = sizeof (struct sockaddr_in));
665     break;
666   case AF_INET6:
667     if (NULL == plugin->sockv6)
668       return 0;
669     sent =
670         GNUNET_NETWORK_socket_sendto (plugin->sockv6, msg, ntohs (msg->size),
671                                       sa, slen = sizeof (struct sockaddr_in6));
672     break;
673   default:
674     GNUNET_break (0);
675     return 0;
676   }
677   if (GNUNET_SYSERR == sent)
678   {
679     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto");
680     LOG (GNUNET_ERROR_TYPE_ERROR,
681          "UDP transmited %u-byte message to %s (%d: %s)\n",
682          (unsigned int) ntohs (msg->size), GNUNET_a2s (sa, slen), (int) sent,
683          (sent < 0) ? STRERROR (errno) : "ok");
684
685   }
686   LOG (GNUNET_ERROR_TYPE_DEBUG,
687        "UDP transmited %u-byte message to %s (%d: %s)\n",
688        (unsigned int) ntohs (msg->size), GNUNET_a2s (sa, slen), (int) sent,
689        (sent < 0) ? STRERROR (errno) : "ok");
690   return sent;
691 }
692
693
694 /**
695  * Function that is called with messages created by the fragmentation
696  * module.  In the case of the 'proc' callback of the
697  * GNUNET_FRAGMENT_context_create function, this function must
698  * eventually call 'GNUNET_FRAGMENT_context_transmission_done'.
699  *
700  * @param cls closure, the 'struct PeerSession'
701  * @param msg the message that was created
702  */
703 static void
704 send_fragment (void *cls, const struct GNUNET_MessageHeader *msg)
705 {
706   struct Session *session = cls;
707
708   udp_send (session->plugin, session->sock_addr, msg);
709   GNUNET_FRAGMENT_context_transmission_done (session->frag);
710 }
711
712
713 static struct Session *
714 create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
715                 const void *addr, size_t addrlen,
716                 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
717 {
718   struct Session *peer_session;
719   const struct IPv4UdpAddress *t4;
720   const struct IPv6UdpAddress *t6;
721   struct sockaddr_in *v4;
722   struct sockaddr_in6 *v6;
723   size_t len;
724
725   switch (addrlen)
726   {
727   case sizeof (struct IPv4UdpAddress):
728     if (NULL == plugin->sockv4)
729     {
730       return NULL;
731     }
732     t4 = addr;
733     peer_session =
734         GNUNET_malloc (sizeof (struct Session) + sizeof (struct sockaddr_in));
735     len = sizeof (struct sockaddr_in);
736     v4 = (struct sockaddr_in *) &peer_session[1];
737     v4->sin_family = AF_INET;
738 #if HAVE_SOCKADDR_IN_SIN_LEN
739     v4->sin_len = sizeof (struct sockaddr_in);
740 #endif
741     v4->sin_port = t4->u4_port;
742     v4->sin_addr.s_addr = t4->ipv4_addr;
743     break;
744   case sizeof (struct IPv6UdpAddress):
745     if (NULL == plugin->sockv6)
746     {
747       return NULL;
748     }
749     t6 = addr;
750     peer_session =
751         GNUNET_malloc (sizeof (struct Session) + sizeof (struct sockaddr_in6));
752     len = sizeof (struct sockaddr_in6);
753     v6 = (struct sockaddr_in6 *) &peer_session[1];
754     v6->sin6_family = AF_INET6;
755 #if HAVE_SOCKADDR_IN_SIN_LEN
756     v6->sin6_len = sizeof (struct sockaddr_in6);
757 #endif
758     v6->sin6_port = t6->u6_port;
759     v6->sin6_addr = t6->ipv6_addr;
760     break;
761   default:
762     /* Must have a valid address to send to */
763     GNUNET_break_op (0);
764     return NULL;
765   }
766
767   peer_session->valid_until = GNUNET_TIME_absolute_get_zero ();
768   peer_session->invalidation_task = GNUNET_SCHEDULER_NO_TASK;
769   peer_session->addrlen = len;
770   peer_session->target = *target;
771   peer_session->plugin = plugin;
772   peer_session->sock_addr = (const struct sockaddr *) &peer_session[1];
773   peer_session->cont = cont;
774   peer_session->cont_cls = cont_cls;
775
776   return peer_session;
777 }
778
779 static const char *
780 udp_address_to_string (void *cls, const void *addr, size_t addrlen);
781
782
783 static void
784 udp_call_continuation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
785 {
786   struct Session *s = cls;
787   GNUNET_TRANSPORT_TransmitContinuation cont = s->cont;
788
789   s->delayed_cont_task = GNUNET_SCHEDULER_NO_TASK;
790   s->cont = NULL;
791   cont (s->cont_cls, &s->target, GNUNET_OK);
792 }
793
794
795 /**
796  * Function that can be used by the transport service to transmit
797  * a message using the plugin.
798  *
799  * @param cls closure
800  * @param target who should receive this message (ignored by UDP)
801  * @param msgbuf one or more GNUNET_MessageHeader(s) strung together
802  * @param msgbuf_size the size of the msgbuf to send
803  * @param priority how important is the message (ignored by UDP)
804  * @param timeout when should we time out (give up) if we can not transmit?
805  * @param session identifier used for this session (NULL for UDP)
806  * @param addr the addr to send the message to
807  * @param addrlen the len of addr
808  * @param force_address not used, we had better have an address to send to
809  *        because we are stateless!!
810  * @param cont continuation to call once the message has
811  *        been transmitted (or if the transport is ready
812  *        for the next transmission call; or if the
813  *        peer disconnected...)
814  * @param cont_cls closure for cont
815  *
816  * @return the number of bytes written (may return 0 and the message can
817  *         still be transmitted later!)
818  */
819 static ssize_t
820 udp_plugin_send (void *cls, const struct GNUNET_PeerIdentity *target,
821                  const char *msgbuf, size_t msgbuf_size, unsigned int priority,
822                  struct GNUNET_TIME_Relative timeout, struct Session *session,
823                  const void *addr, size_t addrlen, int force_address,
824                  GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
825 {
826   struct Plugin *plugin = cls;
827   struct Session *peer_session;
828   struct Session *s;
829   const struct IPv4UdpAddress *t4;
830   const struct IPv6UdpAddress *t6;
831   size_t mlen = msgbuf_size + sizeof (struct UDPMessage);
832   char mbuf[mlen];
833   struct UDPMessage *udp;
834   struct GNUNET_TIME_Relative delta;
835
836   if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
837   {
838     GNUNET_break (0);
839     return GNUNET_SYSERR;
840   }
841
842   LOG (GNUNET_ERROR_TYPE_DEBUG,
843        "UDP transmits %u-byte message to `%s' using address `%s' session 0x%X mode %i\n",
844        msgbuf_size, GNUNET_i2s (target), udp_address_to_string (NULL, addr,
845                                                                 addrlen),
846        session, force_address);
847
848   if ((force_address == GNUNET_SYSERR) && (session == NULL))
849     return GNUNET_SYSERR;
850
851   s = NULL;
852   /* safety check: comparing address to address stored in session */
853   if ((session != NULL) && (addr != NULL) && (addrlen != 0))
854   {
855     s = session;
856     GNUNET_assert (GNUNET_YES ==
857                    GNUNET_CONTAINER_multihashmap_contains_value
858                    (plugin->inbound_sessions, &target->hashPubKey, s));
859
860     if (0 != memcmp (&s->target, target, sizeof (struct GNUNET_PeerIdentity)))
861       return GNUNET_SYSERR;
862     switch (addrlen)
863     {
864     case sizeof (struct IPv4UdpAddress):
865       if (NULL == plugin->sockv4)
866       {
867         if (cont != NULL)
868           cont (cont_cls, target, GNUNET_SYSERR);
869         return GNUNET_SYSERR;
870       }
871       t4 = addr;
872       if (s->addrlen != (sizeof (struct sockaddr_in)))
873         return GNUNET_SYSERR;
874       struct sockaddr_in *a4 = (struct sockaddr_in *) s->sock_addr;
875
876       GNUNET_assert (a4->sin_port == t4->u4_port);
877       GNUNET_assert (0 ==
878                      memcmp (&a4->sin_addr, &t4->ipv4_addr,
879                              sizeof (struct in_addr)));
880       LOG (GNUNET_ERROR_TYPE_DEBUG, "Session 0x%X successfully checked!\n",
881            session);
882       break;
883     case sizeof (struct IPv6UdpAddress):
884       if (NULL == plugin->sockv6)
885       {
886         if (cont != NULL)
887           cont (cont_cls, target, GNUNET_SYSERR);
888         return GNUNET_SYSERR;
889       }
890       t6 = addr;
891       GNUNET_assert (s->addrlen == sizeof (struct sockaddr_in6));
892       struct sockaddr_in6 *a6 = (struct sockaddr_in6 *) s->sock_addr;
893
894       GNUNET_assert (a6->sin6_port == t6->u6_port);
895       GNUNET_assert (0 ==
896                      memcmp (&a6->sin6_addr, &t6->ipv6_addr,
897                              sizeof (struct in6_addr)));
898       LOG (GNUNET_ERROR_TYPE_DEBUG, "Session 0x%X successfully checked!\n",
899            session);
900       break;
901     default:
902       /* Must have a valid address to send to */
903       GNUNET_break_op (0);
904     }
905   }
906 //session_invalid:
907   if ((addr == NULL) || (addrlen == 0))
908     return GNUNET_SYSERR;
909   peer_session = create_session (plugin, target, addr, addrlen, cont, cont_cls);
910   if (peer_session == NULL)
911   {
912     if (cont != NULL)
913       cont (cont_cls, target, GNUNET_SYSERR);
914     return GNUNET_SYSERR;;
915   }
916
917   /* Message */
918   udp = (struct UDPMessage *) mbuf;
919   udp->header.size = htons (mlen);
920   udp->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE);
921   udp->reserved = htonl (0);
922   udp->sender = *plugin->env->my_identity;
923   memcpy (&udp[1], msgbuf, msgbuf_size);
924
925   if (s != NULL)
926     delta = GNUNET_TIME_absolute_get_remaining (s->flow_delay_from_other_peer);
927   else
928     delta = GNUNET_TIME_UNIT_ZERO;
929   if (mlen <= UDP_MTU)
930   {
931     mlen = udp_send (plugin, peer_session->sock_addr, &udp->header);
932     if (cont != NULL)
933     {
934       if ((delta.rel_value > 0) && (mlen > 0))
935       {
936         s->cont = cont;
937         s->cont_cls = cont_cls;
938         s->delayed_cont_task =
939             GNUNET_SCHEDULER_add_delayed (delta, &udp_call_continuation, s);
940       }
941       else
942         cont (cont_cls, target, (mlen > 0) ? GNUNET_OK : GNUNET_SYSERR);
943     }
944     GNUNET_free_non_null (peer_session);
945   }
946   else
947   {
948     GNUNET_assert (GNUNET_OK ==
949                    GNUNET_CONTAINER_multihashmap_put (plugin->sessions,
950                                                       &target->hashPubKey,
951                                                       peer_session,
952                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
953     peer_session->frag =
954         GNUNET_FRAGMENT_context_create (plugin->env->stats, UDP_MTU,
955                                         &plugin->tracker,
956                                         plugin->last_expected_delay,
957                                         &udp->header, &send_fragment,
958                                         peer_session);
959   }
960   return mlen;
961 }
962
963
964 /**
965  * Closure for 'process_inbound_tokenized_messages'
966  */
967 struct SourceInformation
968 {
969   /**
970    * Sender identity.
971    */
972   struct GNUNET_PeerIdentity sender;
973
974   /**
975    * Source address.
976    */
977   const void *arg;
978
979   /**
980    * Number of bytes in source address.
981    */
982   size_t args;
983
984   struct Session *session;
985 };
986
987
988 /**
989  * Message tokenizer has broken up an incomming message. Pass it on
990  * to the service.
991  *
992  * @param cls the 'struct Plugin'
993  * @param client the 'struct SourceInformation'
994  * @param hdr the actual message
995  */
996 static void
997 process_inbound_tokenized_messages (void *cls, void *client,
998                                     const struct GNUNET_MessageHeader *hdr)
999 {
1000   struct Plugin *plugin = cls;
1001   struct SourceInformation *si = client;
1002   struct GNUNET_ATS_Information distance;
1003   struct GNUNET_TIME_Relative delay;
1004
1005   /* setup ATS */
1006   distance.type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
1007   distance.value = htonl (1);
1008
1009   LOG (GNUNET_ERROR_TYPE_DEBUG, "Giving Session %X %s  to transport\n",
1010        si->session, GNUNET_i2s (&si->session->target));
1011   delay =
1012       plugin->env->receive (plugin->env->cls, &si->sender, hdr, &distance, 1,
1013                             si->session, si->arg, si->args);
1014   si->session->flow_delay_for_other_peer = delay;
1015 }
1016
1017 static void
1018 invalidation_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1019 {
1020   struct Session *s = cls;
1021
1022   s->invalidation_task = GNUNET_SCHEDULER_NO_TASK;
1023   LOG (GNUNET_ERROR_TYPE_DEBUG, "Session %X (`%s') is now invalid\n", s,
1024        GNUNET_a2s (s->sock_addr, s->addrlen));
1025
1026   s->plugin->env->session_end (s->plugin->env->cls, &s->target, s);
1027   GNUNET_assert (GNUNET_YES ==
1028                  GNUNET_CONTAINER_multihashmap_remove (s->
1029                                                        plugin->inbound_sessions,
1030                                                        &s->target.hashPubKey,
1031                                                        s));
1032   GNUNET_free (s);
1033 }
1034
1035
1036 /**
1037  * We've received a UDP Message.  Process it (pass contents to main service).
1038  *
1039  * @param plugin plugin context
1040  * @param msg the message
1041  * @param sender_addr sender address
1042  * @param sender_addr_len number of bytes in sender_addr
1043  */
1044 static void
1045 process_udp_message (struct Plugin *plugin, const struct UDPMessage *msg,
1046                      const struct sockaddr *sender_addr,
1047                      socklen_t sender_addr_len)
1048 {
1049   struct SourceInformation si;
1050   struct IPv4UdpAddress u4;
1051   struct IPv6UdpAddress u6;
1052   const void *arg;
1053   size_t args;
1054
1055   if (0 != ntohl (msg->reserved))
1056   {
1057     GNUNET_break_op (0);
1058     return;
1059   }
1060   if (ntohs (msg->header.size) <
1061       sizeof (struct GNUNET_MessageHeader) + sizeof (struct UDPMessage))
1062   {
1063     GNUNET_break_op (0);
1064     return;
1065   }
1066
1067   /* convert address */
1068   switch (sender_addr->sa_family)
1069   {
1070   case AF_INET:
1071     GNUNET_assert (sender_addr_len == sizeof (struct sockaddr_in));
1072     u4.ipv4_addr = ((struct sockaddr_in *) sender_addr)->sin_addr.s_addr;
1073     u4.u4_port = ((struct sockaddr_in *) sender_addr)->sin_port;
1074     arg = &u4;
1075     args = sizeof (u4);
1076     break;
1077   case AF_INET6:
1078     GNUNET_assert (sender_addr_len == sizeof (struct sockaddr_in6));
1079     u6.ipv6_addr = ((struct sockaddr_in6 *) sender_addr)->sin6_addr;
1080     u6.u6_port = ((struct sockaddr_in6 *) sender_addr)->sin6_port;
1081     arg = &u6;
1082     args = sizeof (u6);
1083     break;
1084   default:
1085     GNUNET_break (0);
1086     return;
1087   }
1088 #if DEBUG_UDP
1089   LOG (GNUNET_ERROR_TYPE_DEBUG,
1090        "Received message with %u bytes from peer `%s' at `%s'\n",
1091        (unsigned int) ntohs (msg->header.size), GNUNET_i2s (&msg->sender),
1092        GNUNET_a2s (sender_addr, sender_addr_len));
1093 #endif
1094
1095   /* create a session for inbound connections */
1096   const struct UDPMessage *udp_msg = (const struct UDPMessage *) msg;
1097
1098   LOG (GNUNET_ERROR_TYPE_DEBUG,
1099        "Lookup inbound UDP sessions for peer `%s' address `%s'\n",
1100        GNUNET_i2s (&udp_msg->sender), udp_address_to_string (NULL, arg, args));
1101
1102   struct Session *s = NULL;
1103
1104   s = find_inbound_session (plugin, &udp_msg->sender, sender_addr,
1105                             sender_addr_len);
1106
1107   if (s != NULL)
1108   {
1109     LOG (GNUNET_ERROR_TYPE_DEBUG,
1110          "Found existing inbound UDP sessions 0x%X for peer `%s' address `%s'\n",
1111          s, GNUNET_i2s (&s->target), udp_address_to_string (NULL, arg, args));
1112   }
1113   else
1114   {
1115     s = create_session (plugin, &udp_msg->sender, arg, args, NULL, NULL);
1116     LOG (GNUNET_ERROR_TYPE_DEBUG,
1117          "Creating inbound UDP sessions 0x%X for peer `%s' address `%s'\n", s,
1118          GNUNET_i2s (&s->target), udp_address_to_string (NULL, arg, args));
1119
1120     GNUNET_assert (GNUNET_OK ==
1121                    GNUNET_CONTAINER_multihashmap_put (plugin->inbound_sessions,
1122                                                       &s->target.hashPubKey, s,
1123                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
1124   }
1125   s->valid_until =
1126       GNUNET_TIME_relative_to_absolute
1127       (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1128   if (s->invalidation_task != GNUNET_SCHEDULER_NO_TASK)
1129   {
1130     GNUNET_SCHEDULER_cancel (s->invalidation_task);
1131     s->invalidation_task = GNUNET_SCHEDULER_NO_TASK;
1132     LOG (GNUNET_ERROR_TYPE_DEBUG, "Rescheduling %X' `%s'\n", s,
1133          udp_address_to_string (NULL, arg, args));
1134   }
1135   s->invalidation_task =
1136       GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1137                                     &invalidation_task, s);
1138   /* iterate over all embedded messages */
1139   si.sender = msg->sender;
1140   si.arg = arg;
1141   si.args = args;
1142   si.session = s;
1143   GNUNET_SERVER_mst_receive (plugin->mst, &si, (const char *) &msg[1],
1144                              ntohs (msg->header.size) -
1145                              sizeof (struct UDPMessage), GNUNET_YES, GNUNET_NO);
1146 }
1147
1148
1149 /**
1150  * Process a defragmented message.
1151  *
1152  * @param cls the 'struct ReceiveContext'
1153  * @param msg the message
1154  */
1155 static void
1156 fragment_msg_proc (void *cls, const struct GNUNET_MessageHeader *msg)
1157 {
1158   struct ReceiveContext *rc = cls;
1159
1160   if (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE)
1161   {
1162     GNUNET_break (0);
1163     return;
1164   }
1165   if (ntohs (msg->size) < sizeof (struct UDPMessage))
1166   {
1167     GNUNET_break (0);
1168     return;
1169   }
1170   process_udp_message (rc->plugin, (const struct UDPMessage *) msg,
1171                        rc->src_addr, rc->addr_len);
1172 }
1173
1174
1175 /**
1176  * Transmit an acknowledgement.
1177  *
1178  * @param cls the 'struct ReceiveContext'
1179  * @param id message ID (unused)
1180  * @param msg ack to transmit
1181  */
1182 static void
1183 ack_proc (void *cls, uint32_t id, const struct GNUNET_MessageHeader *msg)
1184 {
1185   struct ReceiveContext *rc = cls;
1186
1187   size_t msize = sizeof (struct UDP_ACK_Message) + ntohs (msg->size);
1188   char buf[msize];
1189   struct UDP_ACK_Message *udp_ack;
1190   uint32_t delay = 0;
1191
1192   struct Session *s;
1193
1194   s = find_inbound_session_by_addr (rc->plugin, rc->src_addr, rc->addr_len);
1195   if (s != NULL)
1196   {
1197     if (s->flow_delay_for_other_peer.rel_value <= UINT32_MAX)
1198       delay = s->flow_delay_for_other_peer.rel_value;
1199     else
1200       delay = UINT32_MAX;
1201   }
1202
1203
1204 #if DEBUG_UDP
1205   LOG (GNUNET_ERROR_TYPE_DEBUG,
1206        "Sending ACK to `%s' including delay of %u ms\n",
1207        GNUNET_a2s (rc->src_addr,
1208                    (rc->src_addr->sa_family ==
1209                     AF_INET) ? sizeof (struct sockaddr_in) : sizeof (struct
1210                                                                      sockaddr_in6)),
1211        delay);
1212 #endif
1213   udp_ack = (struct UDP_ACK_Message *) buf;
1214   udp_ack->header.size = htons ((uint16_t) msize);
1215   udp_ack->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK);
1216   udp_ack->delay = htonl (delay);
1217   udp_ack->sender = *rc->plugin->env->my_identity;
1218   memcpy (&udp_ack[1], msg, ntohs (msg->size));
1219   (void) udp_send (rc->plugin, rc->src_addr, &udp_ack->header);
1220 }
1221
1222
1223 /**
1224  * Closure for 'find_receive_context'.
1225  */
1226 struct FindReceiveContext
1227 {
1228   /**
1229    * Where to store the result.
1230    */
1231   struct ReceiveContext *rc;
1232
1233   /**
1234    * Address to find.
1235    */
1236   const struct sockaddr *addr;
1237
1238   /**
1239    * Number of bytes in 'addr'.
1240    */
1241   socklen_t addr_len;
1242
1243   struct Session *session;
1244 };
1245
1246
1247 /**
1248  * Scan the heap for a receive context with the given address.
1249  *
1250  * @param cls the 'struct FindReceiveContext'
1251  * @param node internal node of the heap
1252  * @param element value stored at the node (a 'struct ReceiveContext')
1253  * @param cost cost associated with the node
1254  * @return GNUNET_YES if we should continue to iterate,
1255  *         GNUNET_NO if not.
1256  */
1257 static int
1258 find_receive_context (void *cls, struct GNUNET_CONTAINER_HeapNode *node,
1259                       void *element, GNUNET_CONTAINER_HeapCostType cost)
1260 {
1261   struct FindReceiveContext *frc = cls;
1262   struct ReceiveContext *e = element;
1263
1264   if ((frc->addr_len == e->addr_len) &&
1265       (0 == memcmp (frc->addr, e->src_addr, frc->addr_len)))
1266   {
1267     frc->rc = e;
1268     return GNUNET_NO;
1269   }
1270   return GNUNET_YES;
1271 }
1272
1273
1274 /**
1275  * Read and process a message from the given socket.
1276  *
1277  * @param plugin the overall plugin
1278  * @param rsock socket to read from
1279  */
1280 static void
1281 udp_read (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock)
1282 {
1283   socklen_t fromlen;
1284   char addr[32];
1285   char buf[65536];
1286   ssize_t ret;
1287   const struct GNUNET_MessageHeader *msg;
1288   const struct GNUNET_MessageHeader *ack;
1289   struct Session *peer_session;
1290   const struct UDP_ACK_Message *udp_ack;
1291   struct ReceiveContext *rc;
1292   struct GNUNET_TIME_Absolute now;
1293   struct FindReceiveContext frc;
1294   struct Session *s = NULL;
1295   struct GNUNET_TIME_Relative flow_delay;
1296
1297   fromlen = sizeof (addr);
1298   memset (&addr, 0, sizeof (addr));
1299   ret =
1300       GNUNET_NETWORK_socket_recvfrom (rsock, buf, sizeof (buf),
1301                                       (struct sockaddr *) &addr, &fromlen);
1302   if (ret < sizeof (struct GNUNET_MessageHeader))
1303   {
1304     GNUNET_break_op (0);
1305     return;
1306   }
1307   msg = (const struct GNUNET_MessageHeader *) buf;
1308
1309   LOG (GNUNET_ERROR_TYPE_DEBUG,
1310        "UDP received %u-byte message from `%s' type %i\n", (unsigned int) ret,
1311        GNUNET_a2s ((const struct sockaddr *) addr, fromlen), ntohs (msg->type));
1312
1313   if (ret != ntohs (msg->size))
1314   {
1315     GNUNET_break_op (0);
1316     return;
1317   }
1318   switch (ntohs (msg->type))
1319   {
1320   case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE:
1321     if (ntohs (msg->size) < sizeof (struct UDPMessage))
1322     {
1323       GNUNET_break_op (0);
1324       return;
1325     }
1326     process_udp_message (plugin, (const struct UDPMessage *) msg,
1327                          (const struct sockaddr *) addr, fromlen);
1328     return;
1329   case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK:
1330
1331     if (ntohs (msg->size) <
1332         sizeof (struct UDP_ACK_Message) + sizeof (struct GNUNET_MessageHeader))
1333     {
1334       GNUNET_break_op (0);
1335       return;
1336     }
1337     udp_ack = (const struct UDP_ACK_Message *) msg;
1338     s = find_inbound_session (plugin, &udp_ack->sender, addr, fromlen);
1339     if (s != NULL)
1340     {
1341       flow_delay.rel_value = (uint64_t) ntohl (udp_ack->delay);
1342
1343       LOG (GNUNET_ERROR_TYPE_DEBUG, "We received a sending delay of %llu\n",
1344            flow_delay.rel_value);
1345
1346       s->flow_delay_from_other_peer =
1347           GNUNET_TIME_relative_to_absolute (flow_delay);
1348     }
1349     ack = (const struct GNUNET_MessageHeader *) &udp_ack[1];
1350     if (ntohs (ack->size) !=
1351         ntohs (msg->size) - sizeof (struct UDP_ACK_Message))
1352     {
1353       GNUNET_break_op (0);
1354       return;
1355     }
1356 #if DEBUG_UDP
1357     LOG (GNUNET_ERROR_TYPE_DEBUG,
1358          "UDP processes %u-byte acknowledgement from `%s' at `%s'\n",
1359          (unsigned int) ntohs (msg->size), GNUNET_i2s (&udp_ack->sender),
1360          GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
1361 #endif
1362
1363     peer_session = find_session (plugin, &udp_ack->sender);
1364     if (NULL == peer_session)
1365     {
1366 #if DEBUG_UDP
1367       LOG (GNUNET_ERROR_TYPE_DEBUG,
1368            "Session for ACK not found, dropping ACK!\n");
1369 #endif
1370       return;
1371     }
1372     if (GNUNET_OK != GNUNET_FRAGMENT_process_ack (peer_session->frag, ack))
1373       return;
1374     GNUNET_assert (GNUNET_OK ==
1375                    GNUNET_CONTAINER_multihashmap_remove (plugin->sessions,
1376                                                          &udp_ack->
1377                                                          sender.hashPubKey,
1378                                                          peer_session));
1379     plugin->last_expected_delay =
1380         GNUNET_FRAGMENT_context_destroy (peer_session->frag);
1381     if (peer_session->cont != NULL)
1382       peer_session->cont (peer_session->cont_cls, &udp_ack->sender, GNUNET_OK);
1383     GNUNET_free (peer_session);
1384     return;
1385   case GNUNET_MESSAGE_TYPE_FRAGMENT:
1386     frc.rc = NULL;
1387     frc.addr = (const struct sockaddr *) addr;
1388     frc.addr_len = fromlen;
1389     GNUNET_CONTAINER_heap_iterate (plugin->defrags, &find_receive_context,
1390                                    &frc);
1391     now = GNUNET_TIME_absolute_get ();
1392     rc = frc.rc;
1393     if (rc == NULL)
1394     {
1395       /* need to create a new RC */
1396       rc = GNUNET_malloc (sizeof (struct ReceiveContext) + fromlen);
1397       memcpy (&rc[1], addr, fromlen);
1398       rc->src_addr = (const struct sockaddr *) &rc[1];
1399       rc->addr_len = fromlen;
1400       rc->plugin = plugin;
1401       rc->defrag =
1402           GNUNET_DEFRAGMENT_context_create (plugin->env->stats, UDP_MTU,
1403                                             UDP_MAX_MESSAGES_IN_DEFRAG, rc,
1404                                             &fragment_msg_proc, &ack_proc);
1405       rc->hnode =
1406           GNUNET_CONTAINER_heap_insert (plugin->defrags, rc,
1407                                         (GNUNET_CONTAINER_HeapCostType)
1408                                         now.abs_value);
1409     }
1410 #if DEBUG_UDP
1411     LOG (GNUNET_ERROR_TYPE_DEBUG, "UDP processes %u-byte fragment from `%s'\n",
1412          (unsigned int) ntohs (msg->size),
1413          GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
1414 #endif
1415
1416     if (GNUNET_OK == GNUNET_DEFRAGMENT_process_fragment (rc->defrag, msg))
1417     {
1418       /* keep this 'rc' from expiring */
1419       GNUNET_CONTAINER_heap_update_cost (plugin->defrags, rc->hnode,
1420                                          (GNUNET_CONTAINER_HeapCostType)
1421                                          now.abs_value);
1422     }
1423     if (GNUNET_CONTAINER_heap_get_size (plugin->defrags) >
1424         UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG)
1425     {
1426       /* remove 'rc' that was inactive the longest */
1427       rc = GNUNET_CONTAINER_heap_remove_root (plugin->defrags);
1428       GNUNET_assert (NULL != rc);
1429       GNUNET_DEFRAGMENT_context_destroy (rc->defrag);
1430       GNUNET_free (rc);
1431     }
1432     return;
1433   default:
1434     GNUNET_break_op (0);
1435     return;
1436   }
1437 }
1438
1439
1440 /**
1441  * We have been notified that our writeset has something to read.  We don't
1442  * know which socket needs to be read, so we have to check each one
1443  * Then reschedule this function to be called again once more is available.
1444  *
1445  * @param cls the plugin handle
1446  * @param tc the scheduling context (for rescheduling this function again)
1447  */
1448 static void
1449 udp_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1450 {
1451   struct Plugin *plugin = cls;
1452
1453   plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
1454   if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
1455     return;
1456   if ((NULL != plugin->sockv4) &&
1457       (GNUNET_NETWORK_fdset_isset (tc->read_ready, plugin->sockv4)))
1458     udp_read (plugin, plugin->sockv4);
1459   if ((NULL != plugin->sockv6) &&
1460       (GNUNET_NETWORK_fdset_isset (tc->read_ready, plugin->sockv6)))
1461     udp_read (plugin, plugin->sockv6);
1462   plugin->select_task =
1463       GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1464                                    GNUNET_SCHEDULER_NO_TASK,
1465                                    GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
1466                                    NULL, &udp_plugin_select, plugin);
1467
1468 }
1469
1470
1471 struct Mstv4Context
1472 {
1473   struct Plugin *plugin;
1474
1475   struct IPv4UdpAddress addr;
1476 };
1477
1478 struct Mstv6Context
1479 {
1480   struct Plugin *plugin;
1481
1482   struct IPv6UdpAddress addr;
1483 };
1484
1485 void
1486 broadcast_ipv4_mst_cb (void *cls, void *client,
1487                       const struct GNUNET_MessageHeader *message)
1488 {
1489   struct Plugin *plugin = cls;
1490   struct Mstv4Context *mc = client;
1491   const struct GNUNET_MessageHeader *hello;
1492   struct UDP_Beacon_Message *msg;
1493
1494   msg = (struct UDP_Beacon_Message *) message;
1495
1496   if (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON !=
1497       ntohs (msg->header.type))
1498     return;
1499
1500   LOG (GNUNET_ERROR_TYPE_DEBUG,
1501        "Received beacon with %u bytes from peer `%s' via address `%s'\n",
1502        ntohs (msg->header.size), GNUNET_i2s (&msg->sender),
1503        udp_address_to_string (NULL, &mc->addr, sizeof (mc->addr)));
1504
1505   struct GNUNET_ATS_Information ats;
1506
1507   ats.type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
1508   ats.value = htonl (1);
1509
1510   hello = (struct GNUNET_MessageHeader *) &msg[1];
1511   plugin->env->receive (plugin->env->cls, &msg->sender, hello, &ats, 1, NULL,
1512                         (const char *) &mc->addr, sizeof (mc->addr));
1513
1514   GNUNET_STATISTICS_update (plugin->env->stats,
1515                             _("# HELLO beacons received via udp"), 1,
1516                             GNUNET_NO);
1517   GNUNET_free (mc);
1518 }
1519
1520
1521 void
1522 broadcast_ipv6_mst_cb (void *cls, void *client,
1523                       const struct GNUNET_MessageHeader *message)
1524 {
1525
1526   struct Plugin *plugin = cls;
1527   struct Mstv6Context *mc = client;
1528   const struct GNUNET_MessageHeader *hello;
1529   struct UDP_Beacon_Message *msg;
1530
1531   msg = (struct UDP_Beacon_Message *) message;
1532
1533   if (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON !=
1534       ntohs (msg->header.type))
1535     return;
1536
1537   LOG (GNUNET_ERROR_TYPE_DEBUG,
1538        "Received beacon with %u bytes from peer `%s' via address `%s'\n",
1539        ntohs (msg->header.size), GNUNET_i2s (&msg->sender),
1540        udp_address_to_string (NULL, &mc->addr, sizeof (mc->addr)));
1541
1542   struct GNUNET_ATS_Information ats;
1543
1544   ats.type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
1545   ats.value = htonl (1);
1546
1547   hello = (struct GNUNET_MessageHeader *) &msg[1];
1548   plugin->env->receive (plugin->env->cls, &msg->sender, hello, &ats, 1, NULL,
1549                         (const char *) &mc->addr, sizeof (mc->addr));
1550
1551   GNUNET_STATISTICS_update (plugin->env->stats,
1552                             _("# HELLO beacons received via udp"), 1,
1553                             GNUNET_NO);
1554   GNUNET_free (mc);
1555 }
1556
1557
1558
1559
1560 /**
1561  * Read and process a message from the given socket.
1562  *
1563  * @param plugin the overall plugin
1564  * @param rsock socket to read from
1565  */
1566 static void
1567 udp_broadcast_read (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock)
1568 {
1569   socklen_t fromlen;
1570   char addr[32];
1571   char buf[65536];
1572   ssize_t ret;
1573
1574
1575
1576   fromlen = sizeof (addr);
1577   memset (&addr, 0, sizeof (addr));
1578   ret =
1579       GNUNET_NETWORK_socket_recvfrom (rsock, buf, sizeof (buf),
1580                                       (struct sockaddr *) &addr, &fromlen);
1581   if (ret < sizeof (struct GNUNET_MessageHeader))
1582   {
1583     /* malformed beacon, just throw it away */
1584     return;
1585   }
1586
1587   if (fromlen == sizeof (struct sockaddr_in))
1588   {
1589     struct Mstv4Context *mc;
1590     mc = GNUNET_malloc (sizeof (struct Mstv4Context));
1591     struct sockaddr_in *av4 = (struct sockaddr_in *) &addr;
1592
1593     mc->addr.ipv4_addr = av4->sin_addr.s_addr;
1594     mc->addr.u4_port = av4->sin_port;
1595     if (GNUNET_OK !=
1596       GNUNET_SERVER_mst_receive (plugin->broadcast_ipv4_mst, mc, buf, ret, GNUNET_NO,
1597                                  GNUNET_NO))
1598     GNUNET_free (mc);
1599   }
1600   else if (fromlen == sizeof (struct sockaddr_in6))
1601   {
1602     LOG (GNUNET_ERROR_TYPE_DEBUG, "Received IPv6 HELLO beacon broadcast with %i bytes from address %s\n",
1603         ret, GNUNET_a2s((const struct sockaddr *) &addr, fromlen));
1604
1605     struct Mstv6Context *mc;
1606     mc = GNUNET_malloc (sizeof (struct Mstv6Context));
1607     struct sockaddr_in6 *av6 = (struct sockaddr_in6 *) &addr;
1608
1609     mc->addr.ipv6_addr = av6->sin6_addr;
1610     mc->addr.u6_port = av6->sin6_port;
1611
1612     if (GNUNET_OK !=
1613         GNUNET_SERVER_mst_receive (plugin->broadcast_ipv6_mst, mc, buf, ret, GNUNET_NO,
1614                                    GNUNET_NO))
1615       GNUNET_free (mc);
1616   }
1617 }
1618
1619
1620 static void
1621 udp_ipv4_broadcast_send (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1622 {
1623   struct Plugin *plugin = cls;
1624   int sent;
1625   uint16_t msg_size;
1626   uint16_t hello_size;
1627   char buf[65536];
1628
1629   const struct GNUNET_MessageHeader *hello;
1630   struct UDP_Beacon_Message *msg;
1631   struct BroadcastAddress * baddr;
1632
1633   plugin->send_ipv4_broadcast_task = GNUNET_SCHEDULER_NO_TASK;
1634
1635
1636   hello = plugin->env->get_our_hello ();
1637   hello_size = GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello);
1638   msg_size = hello_size + sizeof (struct UDP_Beacon_Message);
1639
1640   if (hello_size < (sizeof (struct GNUNET_MessageHeader)) ||
1641       (msg_size > (UDP_MTU)))
1642     return;
1643
1644   msg = (struct UDP_Beacon_Message *) buf;
1645   msg->sender = *(plugin->env->my_identity);
1646   msg->header.size = ntohs (msg_size);
1647   msg->header.type = ntohs (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON);
1648   memcpy (&msg[1], hello, hello_size);
1649   sent = 0;
1650
1651   baddr = plugin->head;
1652   /* just IPv4 */
1653   while ((baddr != NULL) && (baddr->addrlen == sizeof (struct sockaddr_in)))
1654   {
1655     struct sockaddr_in * addr = (struct sockaddr_in * ) baddr->addr;
1656     addr->sin_port = htons (plugin->broadcast_port);
1657
1658     sent = GNUNET_NETWORK_socket_sendto (plugin->sockv4_broadcast, msg, msg_size,
1659                                         (const struct sockaddr *) addr,
1660                                         baddr->addrlen);
1661     if (sent == GNUNET_SYSERR)
1662       GNUNET_log_strerror(GNUNET_ERROR_TYPE_ERROR, "sendto");
1663     else
1664       LOG (GNUNET_ERROR_TYPE_DEBUG, "Sent HELLO beacon broadcast with  %i bytes to address %s\n",
1665            sent, GNUNET_a2s(baddr->addr, baddr->addrlen));
1666       baddr = baddr->next;
1667   }
1668
1669   plugin->send_ipv4_broadcast_task =
1670       GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval,
1671                                     &udp_ipv4_broadcast_send, plugin);
1672 }
1673
1674 static void
1675 udp_ipv6_broadcast_send (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1676 {
1677   struct Plugin *plugin = cls;
1678   int sent;
1679   uint16_t msg_size;
1680   uint16_t hello_size;
1681   char buf[65536];
1682
1683   const struct GNUNET_MessageHeader *hello;
1684   struct UDP_Beacon_Message *msg;
1685
1686   plugin->send_ipv6_broadcast_task = GNUNET_SCHEDULER_NO_TASK;
1687
1688   hello = plugin->env->get_our_hello ();
1689   hello_size = GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello);
1690   msg_size = hello_size + sizeof (struct UDP_Beacon_Message);
1691
1692   if (hello_size < (sizeof (struct GNUNET_MessageHeader)) ||
1693       (msg_size > (UDP_MTU)))
1694     return;
1695
1696   msg = (struct UDP_Beacon_Message *) buf;
1697   msg->sender = *(plugin->env->my_identity);
1698   msg->header.size = ntohs (msg_size);
1699   msg->header.type = ntohs (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON);
1700   memcpy (&msg[1], hello, hello_size);
1701   sent = 0;
1702
1703   sent = GNUNET_NETWORK_socket_sendto (plugin->sockv6_broadcast, msg, msg_size,
1704                                       (const struct sockaddr *) &plugin->ipv6_multicast_address,
1705                                       sizeof(struct sockaddr_in6));
1706   if (sent == GNUNET_SYSERR)
1707     GNUNET_log_strerror(GNUNET_ERROR_TYPE_ERROR, "sendto");
1708   else
1709     LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending IPv6 HELLO beacon broadcast with  %i bytes to address %s\n",
1710        sent, GNUNET_a2s((const struct sockaddr *) &plugin->ipv6_multicast_address, sizeof(struct sockaddr_in6)));
1711
1712
1713
1714   plugin->send_ipv6_broadcast_task =
1715       GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval,
1716                                     &udp_ipv6_broadcast_send, plugin);
1717 }
1718
1719 /**
1720  * We have been notified that our writeset has something to read.  We don't
1721  * know which socket needs to be read, so we have to check each one
1722  * Then reschedule this function to be called again once more is available.
1723  *
1724  * @param cls the plugin handle
1725  * @param tc the scheduling context (for rescheduling this function again)
1726  */
1727 static void
1728 udp_plugin_ipv4_broadcast_select (void *cls,
1729                              const struct GNUNET_SCHEDULER_TaskContext *tc)
1730 {
1731   struct Plugin *plugin = cls;
1732
1733   plugin->select_ipv4_broadcast_task = GNUNET_SCHEDULER_NO_TASK;
1734   if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
1735     return;
1736
1737   if ((NULL != plugin->sockv4_broadcast) &&
1738       (GNUNET_NETWORK_fdset_isset (tc->read_ready, plugin->sockv4_broadcast)))
1739     udp_broadcast_read (plugin, plugin->sockv4_broadcast);
1740
1741   plugin->select_ipv4_broadcast_task =
1742       GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1743                                    GNUNET_SCHEDULER_NO_TASK,
1744                                    GNUNET_TIME_UNIT_FOREVER_REL,
1745                                    plugin->broadcast_ipv4_rs, NULL,
1746                                    &udp_plugin_ipv4_broadcast_select, plugin);
1747 }
1748
1749 /**
1750  * We have been notified that our writeset has something to read.  We don't
1751  * know which socket needs to be read, so we have to check each one
1752  * Then reschedule this function to be called again once more is available.
1753  *
1754  * @param cls the plugin handle
1755  * @param tc the scheduling context (for rescheduling this function again)
1756  */
1757 static void
1758 udp_plugin_ipv6_broadcast_select (void *cls,
1759                              const struct GNUNET_SCHEDULER_TaskContext *tc)
1760 {
1761   struct Plugin *plugin = cls;
1762
1763   plugin->select_ipv6_broadcast_task = GNUNET_SCHEDULER_NO_TASK;
1764   if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
1765     return;
1766
1767   if ((NULL != plugin->sockv6_broadcast) &&
1768       (GNUNET_NETWORK_fdset_isset (tc->read_ready, plugin->sockv6_broadcast)))
1769   {
1770     udp_broadcast_read (plugin, plugin->sockv6_broadcast);
1771   }
1772
1773   plugin->select_ipv6_broadcast_task =
1774       GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1775                                    GNUNET_SCHEDULER_NO_TASK,
1776                                    GNUNET_TIME_UNIT_FOREVER_REL,
1777                                    plugin->broadcast_ipv6_rs, NULL,
1778                                    &udp_plugin_ipv6_broadcast_select, plugin);
1779 }
1780
1781
1782 /**
1783  * Check if the given port is plausible (must be either our listen
1784  * port or our advertised port).  If it is neither, we return
1785  * GNUNET_SYSERR.
1786  *
1787  * @param plugin global variables
1788  * @param in_port port number to check
1789  * @return GNUNET_OK if port is either open_port or adv_port
1790  */
1791 static int
1792 check_port (struct Plugin *plugin, uint16_t in_port)
1793 {
1794   if ((in_port == plugin->port) || (in_port == plugin->aport))
1795     return GNUNET_OK;
1796   return GNUNET_SYSERR;
1797 }
1798
1799
1800 /**
1801  * Function that will be called to check if a binary address for this
1802  * plugin is well-formed and corresponds to an address for THIS peer
1803  * (as per our configuration).  Naturally, if absolutely necessary,
1804  * plugins can be a bit conservative in their answer, but in general
1805  * plugins should make sure that the address does not redirect
1806  * traffic to a 3rd party that might try to man-in-the-middle our
1807  * traffic.
1808  *
1809  * @param cls closure, should be our handle to the Plugin
1810  * @param addr pointer to the address
1811  * @param addrlen length of addr
1812  * @return GNUNET_OK if this is a plausible address for this peer
1813  *         and transport, GNUNET_SYSERR if not
1814  *
1815  */
1816 static int
1817 udp_plugin_check_address (void *cls, const void *addr, size_t addrlen)
1818 {
1819   struct Plugin *plugin = cls;
1820   struct IPv4UdpAddress *v4;
1821   struct IPv6UdpAddress *v6;
1822
1823   if ((addrlen != sizeof (struct IPv4UdpAddress)) &&
1824       (addrlen != sizeof (struct IPv6UdpAddress)))
1825   {
1826     GNUNET_break_op (0);
1827     return GNUNET_SYSERR;
1828   }
1829   if (addrlen == sizeof (struct IPv4UdpAddress))
1830   {
1831     v4 = (struct IPv4UdpAddress *) addr;
1832     if (GNUNET_OK != check_port (plugin, ntohs (v4->u4_port)))
1833       return GNUNET_SYSERR;
1834     if (GNUNET_OK !=
1835         GNUNET_NAT_test_address (plugin->nat, &v4->ipv4_addr,
1836                                  sizeof (struct in_addr)))
1837       return GNUNET_SYSERR;
1838   }
1839   else
1840   {
1841     v6 = (struct IPv6UdpAddress *) addr;
1842     if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr))
1843     {
1844       GNUNET_break_op (0);
1845       return GNUNET_SYSERR;
1846     }
1847     if (GNUNET_OK != check_port (plugin, ntohs (v6->u6_port)))
1848       return GNUNET_SYSERR;
1849     if (GNUNET_OK !=
1850         GNUNET_NAT_test_address (plugin->nat, &v6->ipv6_addr,
1851                                  sizeof (struct in6_addr)))
1852       return GNUNET_SYSERR;
1853   }
1854   return GNUNET_OK;
1855 }
1856
1857
1858 /**
1859  * Function called for a quick conversion of the binary address to
1860  * a numeric address.  Note that the caller must not free the
1861  * address and that the next call to this function is allowed
1862  * to override the address again.
1863  *
1864  * @param cls closure
1865  * @param addr binary address
1866  * @param addrlen length of the address
1867  * @return string representing the same address
1868  */
1869 static const char *
1870 udp_address_to_string (void *cls, const void *addr, size_t addrlen)
1871 {
1872   static char rbuf[INET6_ADDRSTRLEN + 10];
1873   char buf[INET6_ADDRSTRLEN];
1874   const void *sb;
1875   struct in_addr a4;
1876   struct in6_addr a6;
1877   const struct IPv4UdpAddress *t4;
1878   const struct IPv6UdpAddress *t6;
1879   int af;
1880   uint16_t port;
1881
1882   if (addrlen == sizeof (struct IPv6UdpAddress))
1883   {
1884     t6 = addr;
1885     af = AF_INET6;
1886     port = ntohs (t6->u6_port);
1887     memcpy (&a6, &t6->ipv6_addr, sizeof (a6));
1888     sb = &a6;
1889   }
1890   else if (addrlen == sizeof (struct IPv4UdpAddress))
1891   {
1892     t4 = addr;
1893     af = AF_INET;
1894     port = ntohs (t4->u4_port);
1895     memcpy (&a4, &t4->ipv4_addr, sizeof (a4));
1896     sb = &a4;
1897   }
1898   else
1899   {
1900     GNUNET_break_op (0);
1901     return NULL;
1902   }
1903   inet_ntop (af, sb, buf, INET6_ADDRSTRLEN);
1904   GNUNET_snprintf (rbuf, sizeof (rbuf), (af == AF_INET6) ? "[%s]:%u" : "%s:%u",
1905                    buf, port);
1906   return rbuf;
1907 }
1908
1909
1910 /**
1911  * Closure for 'append_port'.
1912  */
1913 struct PrettyPrinterContext
1914 {
1915   /**
1916    * Function to call with the result.
1917    */
1918   GNUNET_TRANSPORT_AddressStringCallback asc;
1919
1920   /**
1921    * Clsoure for 'asc'.
1922    */
1923   void *asc_cls;
1924
1925   /**
1926    * Port to add after the IP address.
1927    */
1928   uint16_t port;
1929 };
1930
1931
1932 /**
1933  * Append our port and forward the result.
1934  *
1935  * @param cls a 'struct PrettyPrinterContext'
1936  * @param hostname result from DNS resolver
1937  */
1938 static void
1939 append_port (void *cls, const char *hostname)
1940 {
1941   struct PrettyPrinterContext *ppc = cls;
1942   char *ret;
1943
1944   if (hostname == NULL)
1945   {
1946     ppc->asc (ppc->asc_cls, NULL);
1947     GNUNET_free (ppc);
1948     return;
1949   }
1950   GNUNET_asprintf (&ret, "%s:%d", hostname, ppc->port);
1951   ppc->asc (ppc->asc_cls, ret);
1952   GNUNET_free (ret);
1953 }
1954
1955
1956 /**
1957  * Convert the transports address to a nice, human-readable
1958  * format.
1959  *
1960  * @param cls closure
1961  * @param type name of the transport that generated the address
1962  * @param addr one of the addresses of the host, NULL for the last address
1963  *        the specific address format depends on the transport
1964  * @param addrlen length of the address
1965  * @param numeric should (IP) addresses be displayed in numeric form?
1966  * @param timeout after how long should we give up?
1967  * @param asc function to call on each string
1968  * @param asc_cls closure for asc
1969  */
1970 static void
1971 udp_plugin_address_pretty_printer (void *cls, const char *type,
1972                                    const void *addr, size_t addrlen,
1973                                    int numeric,
1974                                    struct GNUNET_TIME_Relative timeout,
1975                                    GNUNET_TRANSPORT_AddressStringCallback asc,
1976                                    void *asc_cls)
1977 {
1978   struct PrettyPrinterContext *ppc;
1979   const void *sb;
1980   size_t sbs;
1981   struct sockaddr_in a4;
1982   struct sockaddr_in6 a6;
1983   const struct IPv4UdpAddress *u4;
1984   const struct IPv6UdpAddress *u6;
1985   uint16_t port;
1986
1987   if (addrlen == sizeof (struct IPv6UdpAddress))
1988   {
1989     u6 = addr;
1990     memset (&a6, 0, sizeof (a6));
1991     a6.sin6_family = AF_INET6;
1992 #if HAVE_SOCKADDR_IN_SIN_LEN
1993     a6.sin6_len = sizeof (a6);
1994 #endif
1995     a6.sin6_port = u6->u6_port;
1996     memcpy (&a6.sin6_addr, &u6->ipv6_addr, sizeof (struct in6_addr));
1997     port = ntohs (u6->u6_port);
1998     sb = &a6;
1999     sbs = sizeof (a6);
2000   }
2001   else if (addrlen == sizeof (struct IPv4UdpAddress))
2002   {
2003     u4 = addr;
2004     memset (&a4, 0, sizeof (a4));
2005     a4.sin_family = AF_INET;
2006 #if HAVE_SOCKADDR_IN_SIN_LEN
2007     a4.sin_len = sizeof (a4);
2008 #endif
2009     a4.sin_port = u4->u4_port;
2010     a4.sin_addr.s_addr = u4->ipv4_addr;
2011     port = ntohs (u4->u4_port);
2012     sb = &a4;
2013     sbs = sizeof (a4);
2014   }
2015   else
2016   {
2017     /* invalid address */
2018     GNUNET_break_op (0);
2019     asc (asc_cls, NULL);
2020     return;
2021   }
2022   ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext));
2023   ppc->asc = asc;
2024   ppc->asc_cls = asc_cls;
2025   ppc->port = port;
2026   GNUNET_RESOLVER_hostname_get (sb, sbs, !numeric, timeout, &append_port, ppc);
2027 }
2028
2029
2030 /**
2031  * Our external IP address/port mapping has changed.
2032  *
2033  * @param cls closure, the 'struct LocalAddrList'
2034  * @param add_remove GNUNET_YES to mean the new public IP address, GNUNET_NO to mean
2035  *     the previous (now invalid) one
2036  * @param addr either the previous or the new public IP address
2037  * @param addrlen actual lenght of the address
2038  */
2039 static void
2040 udp_nat_port_map_callback (void *cls, int add_remove,
2041                            const struct sockaddr *addr, socklen_t addrlen)
2042 {
2043   struct Plugin *plugin = cls;
2044   struct IPv4UdpAddress u4;
2045   struct IPv6UdpAddress u6;
2046   void *arg;
2047   size_t args;
2048
2049   /* convert 'addr' to our internal format */
2050   switch (addr->sa_family)
2051   {
2052   case AF_INET:
2053     GNUNET_assert (addrlen == sizeof (struct sockaddr_in));
2054     u4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
2055     u4.u4_port = ((struct sockaddr_in *) addr)->sin_port;
2056     arg = &u4;
2057     args = sizeof (u4);
2058     break;
2059   case AF_INET6:
2060     GNUNET_assert (addrlen == sizeof (struct sockaddr_in6));
2061     memcpy (&u6.ipv6_addr, &((struct sockaddr_in6 *) addr)->sin6_addr,
2062             sizeof (struct in6_addr));
2063     u6.u6_port = ((struct sockaddr_in6 *) addr)->sin6_port;
2064     arg = &u6;
2065     args = sizeof (u6);
2066     break;
2067   default:
2068     GNUNET_break (0);
2069     return;
2070   }
2071   /* modify our published address list */
2072   plugin->env->notify_address (plugin->env->cls, add_remove, arg, args);
2073 }
2074
2075
2076 static int
2077 iface_proc (void *cls, const char *name,
2078             int isDefault,
2079             const struct sockaddr * addr,
2080             const struct sockaddr * broadcast_addr,
2081             const struct sockaddr * netmask,
2082             socklen_t addrlen)
2083 {
2084   struct Plugin *plugin = cls;
2085
2086   if (addr != NULL)
2087   {
2088     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "address %s for interface %s %p\n ",
2089         GNUNET_a2s(addr,addrlen), name, addr);
2090     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "broadcast address %s for interface %s %p\n ",
2091         GNUNET_a2s(broadcast_addr,addrlen), name, broadcast_addr);
2092     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "netmask %s for interface %s %p\n ",
2093         GNUNET_a2s(netmask,addrlen), name, netmask);
2094
2095     if (broadcast_addr != NULL)
2096     {
2097       struct BroadcastAddress * ba = GNUNET_malloc(sizeof (struct BroadcastAddress));
2098       ba->addr = GNUNET_malloc(addrlen);
2099       memcpy(ba->addr, broadcast_addr, addrlen);
2100       ba->addrlen = addrlen;
2101       GNUNET_CONTAINER_DLL_insert(plugin->head, plugin->tail, ba);
2102     }
2103   }
2104   return GNUNET_OK;
2105 }
2106
2107
2108 /**
2109  * The exported method. Makes the core api available via a global and
2110  * returns the udp transport API.
2111  *
2112  * @param cls our 'struct GNUNET_TRANSPORT_PluginEnvironment'
2113  * @return our 'struct GNUNET_TRANSPORT_PluginFunctions'
2114  */
2115 void *
2116 libgnunet_plugin_transport_udp_init (void *cls)
2117 {
2118   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
2119   unsigned long long port;
2120   unsigned long long aport;
2121   unsigned long long bport;
2122   struct GNUNET_TRANSPORT_PluginFunctions *api;
2123   struct Plugin *plugin;
2124   int sockets_created;
2125   int broadcast;
2126   struct GNUNET_TIME_Relative interval;
2127   struct sockaddr_in serverAddrv4;
2128   struct sockaddr_in6 serverAddrv6;
2129   struct sockaddr *serverAddr;
2130   struct sockaddr *addrs[2];
2131   socklen_t addrlens[2];
2132   socklen_t addrlen;
2133   unsigned int tries;
2134   unsigned long long udp_max_bps;
2135
2136   if (GNUNET_OK !=
2137       GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp", "PORT",
2138                                              &port))
2139     port = 2086;
2140
2141   broadcast =
2142       GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "transport-udp",
2143                                             "BROADCAST");
2144   if (broadcast == GNUNET_SYSERR)
2145     broadcast = GNUNET_NO;
2146
2147   if (GNUNET_SYSERR ==
2148       GNUNET_CONFIGURATION_get_value_time (env->cfg, "transport-udp",
2149                                            "BROADCAST_INTERVAL", &interval))
2150     interval = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10);
2151
2152   if (GNUNET_OK !=
2153       GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp",
2154                                              "BROADCAST_PORT", &bport))
2155     bport = 20086;
2156
2157   if (GNUNET_OK !=
2158       GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp",
2159                                              "MAX_BPS", &udp_max_bps))
2160     udp_max_bps = 1024 * 1024 * 50;     /* 50 MB/s == infinity for practical purposes */
2161   if (GNUNET_OK !=
2162       GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp",
2163                                              "ADVERTISED_PORT", &aport))
2164     aport = port;
2165   if (port > 65535)
2166   {
2167     LOG (GNUNET_ERROR_TYPE_WARNING,
2168          _("Given `%s' option is out of range: %llu > %u\n"), "PORT", port,
2169          65535);
2170     return NULL;
2171   }
2172   memset (&serverAddrv6, 0, sizeof (serverAddrv6));
2173   memset (&serverAddrv4, 0, sizeof (serverAddrv4));
2174
2175   plugin = GNUNET_malloc (sizeof (struct Plugin));
2176   GNUNET_BANDWIDTH_tracker_init (&plugin->tracker,
2177                                  GNUNET_BANDWIDTH_value_init ((uint32_t)
2178                                                               udp_max_bps), 30);
2179   plugin->last_expected_delay = GNUNET_TIME_UNIT_SECONDS;
2180   plugin->port = port;
2181   plugin->aport = aport;
2182   plugin->broadcast_port = bport;
2183   plugin->broadcast_ipv4 = broadcast;
2184   plugin->env = env;
2185   plugin->broadcast_interval = interval;
2186   api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
2187   api->cls = plugin;
2188
2189   api->send = &udp_plugin_send;
2190   api->disconnect = &udp_disconnect;
2191   api->address_pretty_printer = &udp_plugin_address_pretty_printer;
2192   api->address_to_string = &udp_address_to_string;
2193   api->check_address = &udp_plugin_check_address;
2194
2195   if (GNUNET_YES ==
2196       GNUNET_CONFIGURATION_get_value_string (env->cfg, "transport-udp",
2197                                              "BINDTO", &plugin->bind4_address))
2198   {
2199     LOG (GNUNET_ERROR_TYPE_DEBUG,
2200          "Binding udp plugin to specific address: `%s'\n",
2201          plugin->bind4_address);
2202     if (1 != inet_pton (AF_INET, plugin->bind4_address, &serverAddrv4.sin_addr))
2203     {
2204       GNUNET_free (plugin->bind4_address);
2205       GNUNET_free (plugin);
2206       GNUNET_free (api);
2207       return NULL;
2208     }
2209   }
2210
2211   if (GNUNET_YES ==
2212       GNUNET_CONFIGURATION_get_value_string (env->cfg, "transport-udp",
2213                                              "BINDTO6", &plugin->bind6_address))
2214   {
2215     LOG (GNUNET_ERROR_TYPE_DEBUG,
2216          "Binding udp plugin to specific address: `%s'\n",
2217          plugin->bind6_address);
2218     if (1 !=
2219         inet_pton (AF_INET6, plugin->bind6_address, &serverAddrv6.sin6_addr))
2220     {
2221       LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid IPv6 address: `%s'\n"),
2222            plugin->bind6_address);
2223       GNUNET_free_non_null (plugin->bind4_address);
2224       GNUNET_free (plugin->bind6_address);
2225       GNUNET_free (plugin);
2226       GNUNET_free (api);
2227       return NULL;
2228     }
2229   }
2230
2231   plugin->defrags =
2232       GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2233   plugin->sessions =
2234       GNUNET_CONTAINER_multihashmap_create (UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG
2235                                             * 2);
2236   plugin->inbound_sessions =
2237       GNUNET_CONTAINER_multihashmap_create (UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG
2238                                             * 2);
2239   sockets_created = 0;
2240   if ((GNUNET_YES !=
2241        GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, "nat",
2242                                              "DISABLEV6")))
2243   {
2244     plugin->sockv6 = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 0);
2245     if (NULL == plugin->sockv6)
2246     {
2247       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket");
2248     }
2249     else
2250     {
2251 #if HAVE_SOCKADDR_IN_SIN_LEN
2252       serverAddrv6.sin6_len = sizeof (serverAddrv6);
2253 #endif
2254       serverAddrv6.sin6_family = AF_INET6;
2255       serverAddrv6.sin6_addr = in6addr_any;
2256       serverAddrv6.sin6_port = htons (plugin->port);
2257       addrlen = sizeof (serverAddrv6);
2258       serverAddr = (struct sockaddr *) &serverAddrv6;
2259 #if DEBUG_UDP
2260       LOG (GNUNET_ERROR_TYPE_DEBUG, "Binding to IPv6 port %d\n",
2261            ntohs (serverAddrv6.sin6_port));
2262 #endif
2263       tries = 0;
2264       while (GNUNET_NETWORK_socket_bind (plugin->sockv6, serverAddr, addrlen) !=
2265              GNUNET_OK)
2266       {
2267         serverAddrv6.sin6_port = htons (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000);        /* Find a good, non-root port */
2268 #if DEBUG_UDP
2269         LOG (GNUNET_ERROR_TYPE_DEBUG,
2270              "IPv6 Binding failed, trying new port %d\n",
2271              ntohs (serverAddrv6.sin6_port));
2272 #endif
2273         tries++;
2274         if (tries > 10)
2275         {
2276           GNUNET_NETWORK_socket_close (plugin->sockv6);
2277           plugin->sockv6 = NULL;
2278           break;
2279         }
2280       }
2281       if (plugin->sockv6 != NULL)
2282       {
2283         addrs[sockets_created] = (struct sockaddr *) &serverAddrv6;
2284         addrlens[sockets_created] = sizeof (serverAddrv6);
2285         sockets_created++;
2286       }
2287     }
2288   }
2289
2290   plugin->mst =
2291       GNUNET_SERVER_mst_create (&process_inbound_tokenized_messages, plugin);
2292   plugin->sockv4 = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 0);
2293   if (NULL == plugin->sockv4)
2294   {
2295     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket");
2296   }
2297   else
2298   {
2299 #if HAVE_SOCKADDR_IN_SIN_LEN
2300     serverAddrv4.sin_len = sizeof (serverAddrv4);
2301 #endif
2302     serverAddrv4.sin_family = AF_INET;
2303     serverAddrv4.sin_addr.s_addr = INADDR_ANY;
2304     serverAddrv4.sin_port = htons (plugin->port);
2305     addrlen = sizeof (serverAddrv4);
2306     serverAddr = (struct sockaddr *) &serverAddrv4;
2307 #if DEBUG_UDP
2308     LOG (GNUNET_ERROR_TYPE_DEBUG, "Binding to IPv4 port %d\n",
2309          ntohs (serverAddrv4.sin_port));
2310 #endif
2311     tries = 0;
2312     while (GNUNET_NETWORK_socket_bind (plugin->sockv4, serverAddr, addrlen) !=
2313            GNUNET_OK)
2314     {
2315       serverAddrv4.sin_port = htons (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000);   /* Find a good, non-root port */
2316 #if DEBUG_UDP
2317       LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv4 Binding failed, trying new port %d\n",
2318            ntohs (serverAddrv4.sin_port));
2319 #endif
2320       tries++;
2321       if (tries > 10)
2322       {
2323         GNUNET_NETWORK_socket_close (plugin->sockv4);
2324         plugin->sockv4 = NULL;
2325         break;
2326       }
2327     }
2328     if (plugin->sockv4 != NULL)
2329     {
2330       addrs[sockets_created] = (struct sockaddr *) &serverAddrv4;
2331       addrlens[sockets_created] = sizeof (serverAddrv4);
2332       sockets_created++;
2333     }
2334   }
2335
2336   plugin->rs = GNUNET_NETWORK_fdset_create ();
2337   GNUNET_NETWORK_fdset_zero (plugin->rs);
2338   if (NULL != plugin->sockv4)
2339     GNUNET_NETWORK_fdset_set (plugin->rs, plugin->sockv4);
2340   if (NULL != plugin->sockv6)
2341     GNUNET_NETWORK_fdset_set (plugin->rs, plugin->sockv6);
2342
2343   plugin->select_task =
2344       GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
2345                                    GNUNET_SCHEDULER_NO_TASK,
2346                                    GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
2347                                    NULL, &udp_plugin_select, plugin);
2348
2349
2350
2351   if (broadcast)
2352   {
2353     /* create IPv4 broadcast socket */
2354     plugin->sockv4_broadcast =
2355         GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 0);
2356     if (NULL == plugin->sockv4_broadcast)
2357     {
2358       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket");
2359     }
2360     else
2361     {
2362 #if HAVE_SOCKADDR_IN_SIN_LEN
2363       serverAddrv4.sin4_len = sizeof (serverAddrv4);
2364 #endif
2365       serverAddrv4.sin_family = AF_INET;
2366       serverAddrv4.sin_addr.s_addr = INADDR_ANY;
2367       serverAddrv4.sin_port = htons (plugin->broadcast_port);
2368       addrlen = sizeof (serverAddrv4);
2369       serverAddr = (struct sockaddr *) &serverAddrv4;
2370 #if DEBUG_UDP
2371 #endif
2372       LOG (GNUNET_ERROR_TYPE_DEBUG, "Binding Broadcast to IPv4 port %d\n",
2373            ntohs (serverAddrv4.sin_port));
2374
2375       if (GNUNET_NETWORK_socket_bind
2376           (plugin->sockv4_broadcast, serverAddr, addrlen) != GNUNET_OK)
2377       {
2378         LOG (GNUNET_ERROR_TYPE_WARNING,
2379              _("Failed to create IPv4 broadcast socket on port %d\n"),
2380              ntohs (serverAddrv4.sin_port));
2381         GNUNET_NETWORK_socket_close (plugin->sockv4_broadcast);
2382         plugin->sockv4_broadcast = NULL;
2383       }
2384       if (plugin->sockv4_broadcast != NULL)
2385       {
2386         int yes = 1;
2387
2388         if (GNUNET_NETWORK_socket_setsockopt
2389             (plugin->sockv4_broadcast, SOL_SOCKET, SO_BROADCAST, &yes,
2390              sizeof (int)) != GNUNET_OK)
2391         {
2392           LOG (GNUNET_ERROR_TYPE_WARNING,
2393                _
2394                ("Failed to set IPv4 broadcast option for broadcast socket on port %d\n"),
2395                ntohs (serverAddrv4.sin_port));
2396           GNUNET_NETWORK_socket_close (plugin->sockv4_broadcast);
2397           plugin->sockv4_broadcast = NULL;
2398         }
2399         else
2400         {
2401           plugin->broadcast_ipv4_rs = GNUNET_NETWORK_fdset_create ();
2402           GNUNET_NETWORK_fdset_set (plugin->broadcast_ipv4_rs,
2403                                     plugin->sockv4_broadcast);
2404         }
2405       }
2406     if (plugin->sockv4_broadcast != NULL)
2407     {
2408       plugin->broadcast_ipv4 = GNUNET_YES;
2409       plugin->broadcast_ipv4_mst =
2410           GNUNET_SERVER_mst_create (broadcast_ipv4_mst_cb, plugin);
2411       GNUNET_STATISTICS_update (plugin->env->stats,
2412                                 _("# HELLO beacons received via udp"), 1,
2413                                 GNUNET_NO);
2414       plugin->select_ipv4_broadcast_task =
2415           GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
2416                                        GNUNET_SCHEDULER_NO_TASK,
2417                                        GNUNET_TIME_UNIT_FOREVER_REL,
2418                                        plugin->broadcast_ipv4_rs, NULL,
2419                                        &udp_plugin_ipv4_broadcast_select, plugin);
2420
2421       GNUNET_OS_network_interfaces_list(iface_proc, plugin);
2422       plugin->send_ipv4_broadcast_task =
2423         GNUNET_SCHEDULER_add_now (&udp_ipv4_broadcast_send, plugin);
2424
2425       LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv4 Broadcasting on port %d running\n",
2426            ntohs (serverAddrv4.sin_port));
2427     }
2428     else
2429       plugin->broadcast_ipv4 = GNUNET_NO;
2430
2431     /* create IPv6 broadcast socket */
2432     plugin->sockv6_broadcast =
2433         GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 0);
2434     if (NULL == plugin->sockv6_broadcast)
2435     {
2436       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket");
2437     }
2438     else
2439     {
2440 #if HAVE_SOCKADDR_IN_SIN_LEN
2441       serverAddrv6.sin_len = sizeof (serverAddrv6);
2442 #endif
2443       serverAddrv6.sin6_family = AF_INET6;
2444       serverAddrv6.sin6_addr = in6addr_any;
2445       serverAddrv6.sin6_port = htons (plugin->broadcast_port);
2446       addrlen = sizeof (serverAddrv6);
2447       serverAddr = (struct sockaddr *) &serverAddrv6;
2448 #if DEBUG_UDP
2449 #endif
2450       LOG (GNUNET_ERROR_TYPE_DEBUG, "Binding Broadcast to IPv6 port %d\n",
2451            ntohs (serverAddrv6.sin6_port));
2452
2453       if (GNUNET_NETWORK_socket_bind
2454           (plugin->sockv6_broadcast, serverAddr, addrlen) != GNUNET_OK)
2455       {
2456         LOG (GNUNET_ERROR_TYPE_WARNING,
2457              _("Failed to create IPv6 broadcast socket on port %d\n"),
2458              ntohs (serverAddrv6.sin6_port));
2459         GNUNET_NETWORK_socket_close (plugin->sockv6_broadcast);
2460         plugin->sockv6_broadcast = NULL;
2461       }
2462       plugin->broadcast_ipv6_rs = GNUNET_NETWORK_fdset_create ();
2463       GNUNET_NETWORK_fdset_set (plugin->broadcast_ipv6_rs,
2464                                 plugin->sockv6_broadcast);
2465       }
2466     }
2467
2468     if (plugin->sockv6_broadcast != NULL)
2469     {
2470       plugin->broadcast_ipv6 = GNUNET_YES;
2471       plugin->broadcast_ipv6_mst =
2472           GNUNET_SERVER_mst_create (broadcast_ipv6_mst_cb, plugin);
2473       plugin->select_ipv6_broadcast_task =
2474           GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
2475                                        GNUNET_SCHEDULER_NO_TASK,
2476                                        GNUNET_TIME_UNIT_FOREVER_REL,
2477                                        plugin->broadcast_ipv6_rs, NULL,
2478                                        &udp_plugin_ipv6_broadcast_select, plugin);
2479
2480       memset (&plugin->ipv6_multicast_address, 0, sizeof (struct sockaddr_in6));
2481       GNUNET_assert (1 == inet_pton(AF_INET6, "ff02::1", &plugin->ipv6_multicast_address.sin6_addr));
2482
2483       plugin->ipv6_multicast_address.sin6_family = AF_INET6;
2484       plugin->ipv6_multicast_address.sin6_port = htons(plugin->broadcast_port);
2485
2486       LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv6 Broadcasting on port %d running\n",
2487            ntohs (serverAddrv6.sin6_port));
2488
2489       plugin->send_ipv6_broadcast_task =
2490         GNUNET_SCHEDULER_add_now (&udp_ipv6_broadcast_send, plugin);
2491     }
2492     else
2493       plugin->broadcast_ipv6 = GNUNET_NO;
2494   }
2495
2496
2497   if (sockets_created == 0)
2498     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to open UDP sockets\n"));
2499   plugin->nat =
2500       GNUNET_NAT_register (env->cfg, GNUNET_NO, port, sockets_created,
2501                            (const struct sockaddr **) addrs, addrlens,
2502                            &udp_nat_port_map_callback, NULL, plugin);
2503   return api;
2504   udp_ipv6_broadcast_send(NULL, NULL);
2505 }
2506
2507 /**
2508  * Shutdown the plugin.
2509  *
2510  * @param cls our 'struct GNUNET_TRANSPORT_PluginFunctions'
2511  * @return NULL
2512  */
2513 void *
2514 libgnunet_plugin_transport_udp_done (void *cls)
2515 {
2516   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
2517   struct Plugin *plugin = api->cls;
2518   struct ReceiveContext *rc;
2519
2520   /* FIXME: clean up heap and hashmap */
2521   GNUNET_CONTAINER_multihashmap_iterate (plugin->sessions, &destroy_session,
2522                                          NULL);
2523   GNUNET_CONTAINER_multihashmap_destroy (plugin->sessions);
2524   plugin->sessions = NULL;
2525   GNUNET_CONTAINER_multihashmap_iterate (plugin->inbound_sessions,
2526                                          &destroy_inbound_session, NULL);
2527   GNUNET_CONTAINER_multihashmap_destroy (plugin->inbound_sessions);
2528   plugin->inbound_sessions = NULL;
2529   while (NULL != (rc = GNUNET_CONTAINER_heap_remove_root (plugin->defrags)))
2530   {
2531     GNUNET_DEFRAGMENT_context_destroy (rc->defrag);
2532     GNUNET_free (rc);
2533   }
2534   GNUNET_CONTAINER_heap_destroy (plugin->defrags);
2535
2536   if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
2537   {
2538     GNUNET_SCHEDULER_cancel (plugin->select_task);
2539     plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
2540   }
2541   if (plugin->sockv4 != NULL)
2542   {
2543     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->sockv4));
2544     plugin->sockv4 = NULL;
2545   }
2546   if (plugin->sockv6 != NULL)
2547   {
2548     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->sockv6));
2549     plugin->sockv6 = NULL;
2550   }
2551
2552   if (plugin->broadcast_ipv4)
2553   {
2554     if (plugin->select_ipv4_broadcast_task != GNUNET_SCHEDULER_NO_TASK)
2555     {
2556       GNUNET_SCHEDULER_cancel (plugin->select_ipv4_broadcast_task);
2557       plugin->select_ipv4_broadcast_task = GNUNET_SCHEDULER_NO_TASK;
2558     }
2559     if (plugin->send_ipv4_broadcast_task != GNUNET_SCHEDULER_NO_TASK)
2560     {
2561       GNUNET_SCHEDULER_cancel (plugin->send_ipv4_broadcast_task);
2562       plugin->send_ipv4_broadcast_task = GNUNET_SCHEDULER_NO_TASK;
2563     }
2564     if (plugin->broadcast_ipv4_mst != NULL)
2565       GNUNET_SERVER_mst_destroy (plugin->broadcast_ipv4_mst);
2566     if (plugin->sockv4_broadcast != NULL)
2567     {
2568       GNUNET_break (GNUNET_OK ==
2569                     GNUNET_NETWORK_socket_close (plugin->sockv4_broadcast));
2570       plugin->sockv4_broadcast = NULL;
2571     }
2572     GNUNET_NETWORK_fdset_destroy (plugin->broadcast_ipv4_rs);
2573
2574     while (plugin->head != NULL)
2575     {
2576       struct BroadcastAddress * p= plugin->head;
2577       GNUNET_CONTAINER_DLL_remove(plugin->head, plugin->tail, p);
2578       GNUNET_free (p->addr);
2579       GNUNET_free (p);
2580     }
2581   }
2582
2583   if (plugin->broadcast_ipv6)
2584   {
2585     if (plugin->select_ipv6_broadcast_task != GNUNET_SCHEDULER_NO_TASK)
2586     {
2587       GNUNET_SCHEDULER_cancel (plugin->select_ipv6_broadcast_task);
2588       plugin->select_ipv6_broadcast_task = GNUNET_SCHEDULER_NO_TASK;
2589     }
2590     if (plugin->send_ipv6_broadcast_task != GNUNET_SCHEDULER_NO_TASK)
2591     {
2592       GNUNET_SCHEDULER_cancel (plugin->send_ipv6_broadcast_task);
2593       plugin->send_ipv6_broadcast_task = GNUNET_SCHEDULER_NO_TASK;
2594     }
2595     if (plugin->broadcast_ipv6_mst != NULL)
2596       GNUNET_SERVER_mst_destroy (plugin->broadcast_ipv6_mst);
2597     if (plugin->sockv6_broadcast != NULL)
2598     {
2599       GNUNET_break (GNUNET_OK ==
2600                     GNUNET_NETWORK_socket_close (plugin->sockv6_broadcast));
2601       plugin->sockv6_broadcast = NULL;
2602     }
2603     GNUNET_NETWORK_fdset_destroy (plugin->broadcast_ipv6_rs);
2604   }
2605
2606   GNUNET_SERVER_mst_destroy (plugin->mst);
2607   GNUNET_NETWORK_fdset_destroy (plugin->rs);
2608
2609   GNUNET_NAT_unregister (plugin->nat);
2610   plugin->nat = NULL;
2611   GNUNET_free (plugin);
2612   GNUNET_free (api);
2613   return NULL;
2614 }
2615
2616 /* end of plugin_transport_udp.c */