REST/NAMESTORE: rework API
[oweals/gnunet.git] / src / transport / gnunet-communicator-udp.c
index 12c409b3d376fbd125b206dabb12513866162163..9420b9b5c06e7f31b2f0c8bbc562d262d27e7c1b 100644 (file)
  * @author Christian Grothoff
  *
  * TODO:
- * - figure out what to do with MTU: 1280 for IPv6 is obvious;
- *   what for IPv4? 1500? Also, consider differences in 
- *   headers for with/without box: need to give MIN of both
- *   to TNG (as TNG expects a fixed MTU!), or maybe
- *   we create a FRESH MQ while we have available BOXes SQNs?
- *   (otherwise padding will REALLY hurt)
- * - add and use util/ check for IPv6 availability (#V6)
  * - consider imposing transmission limits in the absence
  *   of ACKs; or: maybe this should be done at TNG service level?
- * - handle addresses discovered from broadcasts (#)
+ *   (at least the receiver might want to enforce limits on
+ *    KX/DH operations per sender in here) (#5552)
+ * - overall, we should look more into flow control support
+ *   (either in backchannel, or general solution in TNG service)
+ * - handle addresses discovered from broadcasts (#5551)
  *   (think: what was the story again on address validation?
  *    where is the API for that!?!)
  * - support DNS names in BINDTO option (#5528)
  * - support NAT connection reversal method (#5529)
- * - support other UDP-specific NAT traversal methods (#) 
+ * - support other UDP-specific NAT traversal methods (#)
  */
 #include "platform.h"
 #include "gnunet_util_lib.h"
 #include "gnunet_nt_lib.h"
 #include "gnunet_nat_service.h"
 #include "gnunet_statistics_service.h"
+#include "gnunet_transport_application_service.h"
 #include "gnunet_transport_communication_service.h"
 
 /**
  * How often do we rekey based on time (at least)
- */ 
+ */
 #define REKEY_TIME_INTERVAL GNUNET_TIME_UNIT_DAYS
 
 /**
  * How long do we wait until we must have received the initial KX?
- */ 
+ */
 #define PROTO_QUEUE_TIMEOUT GNUNET_TIME_UNIT_MINUTES
 
 /**
  * How often do we broadcast our presence on the LAN?
- */ 
+ */
 #define BROADCAST_FREQUENCY GNUNET_TIME_UNIT_MINUTES
 
 /**
  * How often do we scan for changes to our network interfaces?
- */ 
-#define INTERFACE_SCAN_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
+ */
+#define INTERFACE_SCAN_FREQUENCY \
+  GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
+
+/**
+ * How long do we believe our addresses to remain up (before
+ * the other peer should revalidate).
+ */
+#define ADDRESS_VALIDITY_PERIOD GNUNET_TIME_UNIT_HOURS
 
 /**
  * AES key size.
  */
-#define AES_KEY_SIZE (256/8)
+#define AES_KEY_SIZE (256 / 8)
 
 /**
  * AES (GCM) IV size.
  */
-#define AES_IV_SIZE (96/8)
+#define AES_IV_SIZE (96 / 8)
 
 /**
  * Size of the GCM tag.
  */
-#define GCM_TAG_SIZE (128/8)
+#define GCM_TAG_SIZE (128 / 8)
 
 /**
  * If we fall below this number of available KCNs,
@@ -91,7 +96,7 @@
  * #KCN_TARGET.
  * Should be large enough that we don't generate ACKs all
  * the time and still have enough time for the ACK to
- * arrive before the sender runs out. So really this 
+ * arrive before the sender runs out. So really this
  * should ideally be based on the RTT.
  */
 #define KCN_THRESHOLD 92
 #define MAX_SQN_DELTA 160
 
 /**
- * How many shared master secrets do we keep around 
- * at most per sender?  Should be large enough so 
+ * How many shared master secrets do we keep around
+ * at most per sender?  Should be large enough so
  * that we generally have a chance of sending an ACK
  * before the sender already rotated out the master
  * secret.  Generally values around #KCN_TARGET make
 /**
  * How often do we rekey based on number of bytes transmitted?
  * (additionally randomized).
- */ 
+ */
 #define REKEY_MAX_BYTES (1024LLU * 1024 * 1024 * 4LLU)
 
 /**
@@ -160,23 +165,23 @@ struct UdpHandshakeSignature
 
   /**
    * Identity of the inititor of the UDP connection (UDP client).
-   */ 
+   */
   struct GNUNET_PeerIdentity sender;
 
   /**
    * Presumed identity of the target of the UDP connection (UDP server)
-   */ 
+   */
   struct GNUNET_PeerIdentity receiver;
 
   /**
    * Ephemeral key used by the @e sender.
-   */ 
+   */
   struct GNUNET_CRYPTO_EcdhePublicKey ephemeral;
 
   /**
    * Monotonic time of @e sender, to possibly help detect replay attacks
    * (if receiver persists times by sender).
-   */ 
+   */
   struct GNUNET_TIME_AbsoluteNBO monotonic_time;
 };
 
@@ -190,15 +195,14 @@ struct InitialKX
 
   /**
    * Ephemeral key for KX.
-   */ 
+   */
   struct GNUNET_CRYPTO_EcdhePublicKey ephemeral;
 
   /**
    * HMAC for the following encrypted message, using GCM.  HMAC uses
    * key derived from the handshake with sequence number zero.
-   */ 
+   */
   char gcm_tag[GCM_TAG_SIZE];
-
 };
 
 
@@ -221,7 +225,7 @@ struct UDPConfirmation
   /**
    * Monotonic time of @e sender, to possibly help detect replay attacks
    * (if receiver persists times by sender).
-   */ 
+   */
   struct GNUNET_TIME_AbsoluteNBO monotonic_time;
 
   /* followed by messages */
@@ -233,26 +237,25 @@ struct UDPConfirmation
 /**
  * UDP key acknowledgement.  May be sent via backchannel. Allows the
  * sender to use `struct UDPBox` with the acknowledge key henceforth.
- */ 
+ */
 struct UDPAck
 {
 
   /**
    * Type is #GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_ACK.
-   */ 
+   */
   struct GNUNET_MessageHeader header;
 
   /**
    * Sequence acknowledgement limit. Specifies current maximum sequence
    * number supported by receiver.
-   */ 
+   */
   uint32_t sequence_max GNUNET_PACKED;
-  
+
   /**
    * CMAC of the base key being acknowledged.
-   */ 
+   */
   struct GNUNET_HashCode cmac;
-
 };
 
 
@@ -260,7 +263,7 @@ struct UDPAck
  * Signature we use to verify that the broadcast was really made by
  * the peer that claims to have made it.  Basically, affirms that the
  * peer is really using this IP address (albeit possibly not in _our_
- * LAN).  Makes it difficult for peers in the LAN to claim to 
+ * LAN).  Makes it difficult for peers in the LAN to claim to
  * be just any global peer -- an attacker must have at least
  * shared a LAN with the peer they're pretending to be here.
  */
@@ -273,12 +276,12 @@ struct UdpBroadcastSignature
 
   /**
    * Identity of the inititor of the UDP broadcast.
-   */ 
+   */
   struct GNUNET_PeerIdentity sender;
 
   /**
    * Hash of the sender's UDP address.
-   */ 
+   */
   struct GNUNET_HashCode h_address;
 };
 
@@ -301,22 +304,21 @@ struct UDPBroadcast
    * Sender's signature of type
    * #GNUNET_SIGNATURE_COMMUNICATOR_UDP_BROADCAST
    */
-  struct GNUNET_CRYPTO_EddsaSignature sender_sig;  
-  
+  struct GNUNET_CRYPTO_EddsaSignature sender_sig;
 };
 
 
 /**
  * UDP message box.  Always sent encrypted, only allowed after
  * the receiver sent a `struct UDPAck` for the base key!
- */ 
+ */
 struct UDPBox
 {
 
   /**
    * Key and IV identification code. KDF applied to an acknowledged
    * base key and a sequence number.  Sequence numbers must be used
-   * monotonically increasing up to the maximum specified in 
+   * monotonically increasing up to the maximum specified in
    * `struct UDPAck`. Without further `struct UDPAck`s, the sender
    * must fall back to sending handshakes!
    */
@@ -328,9 +330,8 @@ struct UDPBox
    * extends until the end of the UDP payload.  If the @e hmac is
    * wrong, the receiver should check if the message might be a
    * `struct UdpHandshakeSignature`.
-   */ 
+   */
   char gcm_tag[GCM_TAG_SIZE];
-  
 };
 
 
@@ -353,7 +354,7 @@ struct KeyCacheEntry
    * Kept in a DLL.
    */
   struct KeyCacheEntry *next;
-  
+
   /**
    * Kept in a DLL.
    */
@@ -362,7 +363,7 @@ struct KeyCacheEntry
   /**
    * Key and IV identification code. KDF applied to an acknowledged
    * base key and a sequence number.  Sequence numbers must be used
-   * monotonically increasing up to the maximum specified in 
+   * monotonically increasing up to the maximum specified in
    * `struct UDPAck`. Without further `struct UDPAck`s, the sender
    * must fall back to sending handshakes!
    */
@@ -375,7 +376,7 @@ struct KeyCacheEntry
 
   /**
    * Sequence number used to derive this entry from master key.
-   */ 
+   */
   uint32_t sequence_number;
 };
 
@@ -411,7 +412,7 @@ struct SharedSecret
    * Kept in a DLL, sorted by sequence number. Only if we are decrypting.
    */
   struct KeyCacheEntry *kce_head;
-  
+
   /**
    * Kept in a DLL, sorted by sequence number. Only if we are decrypting.
    */
@@ -426,21 +427,21 @@ struct SharedSecret
    * Receiver we use this shared secret with, or NULL.
    */
   struct ReceiverAddress *receiver;
-  
+
   /**
    * Master shared secret.
-   */ 
+   */
   struct GNUNET_HashCode master;
 
   /**
    * CMAC is used to identify @e master in ACKs.
-   */ 
+   */
   struct GNUNET_HashCode cmac;
 
   /**
    * Up to which sequence number did we use this @e master already?
    * (for encrypting only)
-   */ 
+   */
   uint32_t sequence_used;
 
   /**
@@ -452,7 +453,7 @@ struct SharedSecret
 
   /**
    * Number of active KCN entries.
-   */ 
+   */
   unsigned int active_kce_count;
 };
 
@@ -467,11 +468,11 @@ struct SenderAddress
   /**
    * To whom are we talking to.
    */
-  struct GNUNET_PeerIdentity target;  
+  struct GNUNET_PeerIdentity target;
 
   /**
    * Entry in sender expiration heap.
-   */ 
+   */
   struct GNUNET_CONTAINER_HeapNode *hn;
 
   /**
@@ -483,12 +484,12 @@ struct SenderAddress
    * Shared secrets we used with @e target, last used is tail.
    */
   struct SharedSecret *ss_tail;
-  
+
   /**
    * Address of the other peer.
    */
   struct sockaddr *address;
-  
+
   /**
    * Length of the address.
    */
@@ -501,14 +502,13 @@ struct SenderAddress
 
   /**
    * Length of the DLL at @a ss_head.
-   */ 
+   */
   unsigned int num_secrets;
-  
+
   /**
    * Which network type does this queue use?
    */
   enum GNUNET_NetworkType nt;
-  
 };
 
 
@@ -522,8 +522,8 @@ struct ReceiverAddress
   /**
    * To whom are we talking to.
    */
-  struct GNUNET_PeerIdentity target;  
-  
+  struct GNUNET_PeerIdentity target;
+
   /**
    * Shared secrets we received from @e target, first used is head.
    */
@@ -534,11 +534,17 @@ struct ReceiverAddress
    */
   struct SharedSecret *ss_tail;
 
+  /**
+   * Address of the receiver in the human-readable format
+   * with the #COMMUNICATOR_ADDRESS_PREFIX.
+   */
+  char *foreign_addr;
+
   /**
    * Address of the other peer.
    */
   struct sockaddr *address;
-  
+
   /**
    * Length of the address.
    */
@@ -546,7 +552,7 @@ struct ReceiverAddress
 
   /**
    * Entry in sender expiration heap.
-   */ 
+   */
   struct GNUNET_CONTAINER_HeapNode *hn;
 
   /**
@@ -568,23 +574,22 @@ struct ReceiverAddress
    * MTU we allowed transport for this receiver right now.
    */
   size_t mtu;
-  
+
   /**
    * Length of the DLL at @a ss_head.
-   */ 
+   */
   unsigned int num_secrets;
 
   /**
-   * Number of BOX keys from ACKs we have currently 
+   * Number of BOX keys from ACKs we have currently
    * available for this receiver.
-   */ 
+   */
   unsigned int acks_available;
-  
+
   /**
    * Which network type does this queue use?
    */
   enum GNUNET_NetworkType nt;
-  
 };
 
 
@@ -608,12 +613,12 @@ struct BroadcastInterface
    * Task for this broadcast interface.
    */
   struct GNUNET_SCHEDULER_Task *broadcast_task;
-  
+
   /**
    * Sender's address of the interface.
    */
   struct sockaddr *sa;
-  
+
   /**
    * Broadcast address to use on the interface.
    */
@@ -621,18 +626,18 @@ struct BroadcastInterface
 
   /**
    * Message we broadcast on this interface.
-   */ 
+   */
   struct UDPBroadcast bcm;
-  
+
   /**
    * If this is an IPv6 interface, this is the request
    * we use to join/leave the group.
    */
   struct ipv6_mreq mcreq;
-  
+
   /**
    * Number of bytes in @e sa.
-   */ 
+   */
   socklen_t salen;
 
   /**
@@ -707,9 +712,9 @@ static struct BroadcastInterface *bi_tail;
  */
 static struct GNUNET_NETWORK_Handle *udp_sock;
 
-/** 
+/**
  * #GNUNET_YES if #udp_sock supports IPv6.
- */ 
+ */
 static int have_v6_socket;
 
 /**
@@ -727,6 +732,11 @@ static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
  */
 static const struct GNUNET_CONFIGURATION_Handle *cfg;
 
+/**
+ * Our handle to report addresses for validation to TRANSPORT.
+ */
+static struct GNUNET_TRANSPORT_ApplicationHandle *ah;
+
 /**
  * Network scanner to determine network types.
  */
@@ -739,7 +749,7 @@ static struct GNUNET_NAT_Handle *nat;
 
 /**
  * Port number to which we are actually bound.
- */ 
+ */
 static uint16_t my_port;
 
 
@@ -754,21 +764,16 @@ bi_destroy (struct BroadcastInterface *bi)
   if (AF_INET6 == bi->sa->sa_family)
   {
     /* Leave the multicast group */
-    if (GNUNET_OK !=
-        GNUNET_NETWORK_socket_setsockopt
-        (udp_sock,
-        IPPROTO_IPV6,
-        IPV6_LEAVE_GROUP,
-         &bi->mcreq,
-        sizeof (bi->mcreq)))
+    if (GNUNET_OK != GNUNET_NETWORK_socket_setsockopt (udp_sock,
+                                                       IPPROTO_IPV6,
+                                                       IPV6_LEAVE_GROUP,
+                                                       &bi->mcreq,
+                                                       sizeof (bi->mcreq)))
     {
-      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
-                          "setsockopt");
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
     }
   }
-  GNUNET_CONTAINER_DLL_remove (bi_head,
-                              bi_tail,
-                              bi);
+  GNUNET_CONTAINER_DLL_remove (bi_head, bi_tail, bi);
   GNUNET_SCHEDULER_cancel (bi->broadcast_task);
   GNUNET_free (bi->sa);
   GNUNET_free_non_null (bi->ba);
@@ -785,26 +790,31 @@ static void
 receiver_destroy (struct ReceiverAddress *receiver)
 {
   struct GNUNET_MQ_Handle *mq;
-  
+
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Disconnecting receiver for peer `%s'\n",
-             GNUNET_i2s (&receiver->target));
+              "Disconnecting receiver for peer `%s'\n",
+              GNUNET_i2s (&receiver->target));
   if (NULL != (mq = receiver->mq))
   {
     receiver->mq = NULL;
     GNUNET_MQ_destroy (mq);
   }
+  if (NULL != receiver->qh)
+  {
+    GNUNET_TRANSPORT_communicator_mq_del (receiver->qh);
+    receiver->qh = NULL;
+  }
   GNUNET_assert (GNUNET_YES ==
                  GNUNET_CONTAINER_multipeermap_remove (receivers,
-                                                      &receiver->target,
-                                                      receiver));
-  GNUNET_assert (receiver ==
-                GNUNET_CONTAINER_heap_remove_node (receiver->hn));
+                                                       &receiver->target,
+                                                       receiver));
+  GNUNET_assert (receiver == GNUNET_CONTAINER_heap_remove_node (receiver->hn));
   GNUNET_STATISTICS_set (stats,
-                        "# receivers active",
-                        GNUNET_CONTAINER_multipeermap_size (receivers),
-                        GNUNET_NO);
+                         "# receivers active",
+                         GNUNET_CONTAINER_multipeermap_size (receivers),
+                         GNUNET_NO);
   GNUNET_free (receiver->address);
+  GNUNET_free (receiver->foreign_addr);
   GNUNET_free (receiver);
 }
 
@@ -813,20 +823,17 @@ receiver_destroy (struct ReceiverAddress *receiver)
  * Free memory used by key cache entry.
  *
  * @param kce the key cache entry
- */ 
+ */
 static void
 kce_destroy (struct KeyCacheEntry *kce)
 {
   struct SharedSecret *ss = kce->ss;
 
   ss->active_kce_count--;
-  GNUNET_CONTAINER_DLL_remove (ss->kce_head,
-                              ss->kce_tail,
-                              kce);
-  GNUNET_assert (GNUNET_YES ==
-                GNUNET_CONTAINER_multishortmap_remove (key_cache,
-                                                       &kce->kid,
-                                                       kce));
+  GNUNET_CONTAINER_DLL_remove (ss->kce_head, ss->kce_tail, kce);
+  GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multishortmap_remove (key_cache,
+                                                                      &kce->kid,
+                                                                      kce));
   GNUNET_free (kce);
 }
 
@@ -840,22 +847,23 @@ kce_destroy (struct KeyCacheEntry *kce)
  */
 static void
 get_kid (const struct GNUNET_HashCode *msec,
-        uint32_t serial,
-        struct GNUNET_ShortHashCode *kid)
+         uint32_t serial,
+         struct GNUNET_ShortHashCode *kid)
 {
   uint32_t sid = htonl (serial);
 
   GNUNET_CRYPTO_hkdf (kid,
-                     sizeof (*kid),
-                     GCRY_MD_SHA512,
-                     GCRY_MD_SHA256,
-                     &sid,
-                     sizeof (sid),
-                     msec,
-                     sizeof (*msec),
-                     "UDP-KID",
-                     strlen ("UDP-KID"),
-                     NULL, 0);
+                      sizeof (*kid),
+                      GCRY_MD_SHA512,
+                      GCRY_MD_SHA256,
+                      &sid,
+                      sizeof (sid),
+                      msec,
+                      sizeof (*msec),
+                      "UDP-KID",
+                      strlen ("UDP-KID"),
+                      NULL,
+                      0);
 }
 
 
@@ -866,8 +874,7 @@ get_kid (const struct GNUNET_HashCode *msec,
  * @param seq sequence number for the key cache entry
  */
 static void
-kce_generate (struct SharedSecret *ss,
-             uint32_t seq)
+kce_generate (struct SharedSecret *ss, uint32_t seq)
 {
   struct KeyCacheEntry *kce;
 
@@ -875,21 +882,18 @@ kce_generate (struct SharedSecret *ss,
   kce = GNUNET_new (struct KeyCacheEntry);
   kce->ss = ss;
   kce->sequence_number = seq;
-  get_kid (&ss->master,
-          seq,
-          &kce->kid);
-  GNUNET_CONTAINER_DLL_insert (ss->kce_head,
-                              ss->kce_tail,
-                              kce);
+  get_kid (&ss->master, seq, &kce->kid);
+  GNUNET_CONTAINER_DLL_insert (ss->kce_head, ss->kce_tail, kce);
   ss->active_kce_count++;
-  (void) GNUNET_CONTAINER_multishortmap_put (key_cache,
-                                            &kce->kid,
-                                            kce,
-                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+  (void) GNUNET_CONTAINER_multishortmap_put (
+    key_cache,
+    &kce->kid,
+    kce,
+    GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
   GNUNET_STATISTICS_set (stats,
-                        "# KIDs active",
-                        GNUNET_CONTAINER_multishortmap_size (key_cache),
-                        GNUNET_NO);
+                         "# KIDs active",
+                         GNUNET_CONTAINER_multishortmap_size (key_cache),
+                         GNUNET_NO);
 }
 
 
@@ -907,30 +911,22 @@ secret_destroy (struct SharedSecret *ss)
 
   if (NULL != (sender = ss->sender))
   {
-    GNUNET_CONTAINER_DLL_remove (sender->ss_head,
-                                sender->ss_tail,
-                                ss);
+    GNUNET_CONTAINER_DLL_remove (sender->ss_head, sender->ss_tail, ss);
     sender->num_secrets--;
   }
   if (NULL != (receiver = ss->receiver))
   {
-    GNUNET_CONTAINER_DLL_remove (receiver->ss_head,
-                                receiver->ss_tail,
-                                ss);
+    GNUNET_CONTAINER_DLL_remove (receiver->ss_head, receiver->ss_tail, ss);
     receiver->num_secrets--;
-    receiver->acks_available
-      -= (ss->sequence_allowed - ss->sequence_used);
+    receiver->acks_available -= (ss->sequence_allowed - ss->sequence_used);
   }
   while (NULL != (kce = ss->kce_head))
     kce_destroy (kce);
-  GNUNET_STATISTICS_update (stats,
-                           "# Secrets active",
-                           -1,
-                           GNUNET_NO);
+  GNUNET_STATISTICS_update (stats, "# Secrets active", -1, GNUNET_NO);
   GNUNET_STATISTICS_set (stats,
-                        "# KIDs active",
-                        GNUNET_CONTAINER_multishortmap_size (key_cache),
-                        GNUNET_NO);
+                         "# KIDs active",
+                         GNUNET_CONTAINER_multishortmap_size (key_cache),
+                         GNUNET_NO);
   GNUNET_free (ss);
 }
 
@@ -944,16 +940,14 @@ secret_destroy (struct SharedSecret *ss)
 static void
 sender_destroy (struct SenderAddress *sender)
 {
-  GNUNET_assert (GNUNET_YES ==
-                 GNUNET_CONTAINER_multipeermap_remove (senders,
-                                                      &sender->target,
-                                                      sender));
-  GNUNET_assert (sender ==
-                GNUNET_CONTAINER_heap_remove_node (sender->hn));
+  GNUNET_assert (
+    GNUNET_YES ==
+    GNUNET_CONTAINER_multipeermap_remove (senders, &sender->target, sender));
+  GNUNET_assert (sender == GNUNET_CONTAINER_heap_remove_node (sender->hn));
   GNUNET_STATISTICS_set (stats,
-                        "# senders active",
-                        GNUNET_CONTAINER_multipeermap_size (senders),
-                        GNUNET_NO);
+                         "# senders active",
+                         GNUNET_CONTAINER_multipeermap_size (senders),
+                         GNUNET_NO);
   GNUNET_free (sender->address);
   GNUNET_free (sender);
 }
@@ -969,30 +963,27 @@ sender_destroy (struct SenderAddress *sender)
  */
 static void
 get_iv_key (const struct GNUNET_HashCode *msec,
-           uint32_t serial,
-           char key[AES_KEY_SIZE],
-           char iv[AES_IV_SIZE])
+            uint32_t serial,
+            char key[AES_KEY_SIZE],
+            char iv[AES_IV_SIZE])
 {
   uint32_t sid = htonl (serial);
   char res[AES_KEY_SIZE + AES_IV_SIZE];
 
   GNUNET_CRYPTO_hkdf (res,
-                     sizeof (res),
-                     GCRY_MD_SHA512,
-                     GCRY_MD_SHA256,
-                     &sid,
-                     sizeof (sid),
-                     msec,
-                     sizeof (*msec),
-                     "UDP-IV-KEY",
-                     strlen ("UDP-IV-KEY"),
-                     NULL, 0);
-  memcpy (key,
-         res,
-         AES_KEY_SIZE);
-  memcpy (iv,
-         &res[AES_KEY_SIZE],
-         AES_IV_SIZE);
+                      sizeof (res),
+                      GCRY_MD_SHA512,
+                      GCRY_MD_SHA256,
+                      &sid,
+                      sizeof (sid),
+                      msec,
+                      sizeof (*msec),
+                      "UDP-IV-KEY",
+                      strlen ("UDP-IV-KEY"),
+                      NULL,
+                      0);
+  memcpy (key, res, AES_KEY_SIZE);
+  memcpy (iv, &res[AES_KEY_SIZE], AES_IV_SIZE);
 }
 
 
@@ -1004,10 +995,9 @@ get_iv_key (const struct GNUNET_HashCode *msec,
 static void
 reschedule_sender_timeout (struct SenderAddress *sender)
 {
-  sender->timeout
-    = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
-  GNUNET_CONTAINER_heap_update_cost (sender->hn,
-                                    sender->timeout.abs_value_us);
+  sender->timeout =
+    GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
+  GNUNET_CONTAINER_heap_update_cost (sender->hn, sender->timeout.abs_value_us);
 }
 
 
@@ -1019,10 +1009,10 @@ reschedule_sender_timeout (struct SenderAddress *sender)
 static void
 reschedule_receiver_timeout (struct ReceiverAddress *receiver)
 {
-  receiver->timeout
-    GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
+  receiver->timeout =
+    GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
   GNUNET_CONTAINER_heap_update_cost (receiver->hn,
-                                    receiver->timeout.abs_value_us);
+                                     receiver->timeout.abs_value_us);
 }
 
 
@@ -1039,7 +1029,7 @@ check_timeouts (void *cls)
   struct GNUNET_TIME_Relative delay;
   struct ReceiverAddress *receiver;
   struct SenderAddress *sender;
-  
+
   (void) cls;
   timeout_task = NULL;
   rt = GNUNET_TIME_UNIT_FOREVER_REL;
@@ -1058,14 +1048,11 @@ check_timeouts (void *cls)
       break;
     sender_destroy (sender);
   }
-  delay = GNUNET_TIME_relative_min (rt,
-                                   st);
+  delay = GNUNET_TIME_relative_min (rt, st);
   if (delay.rel_value_us < GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
-    timeout_task = GNUNET_SCHEDULER_add_delayed (delay,
-                                                &check_timeouts,
-                                                NULL);  
+    timeout_task = GNUNET_SCHEDULER_add_delayed (delay, &check_timeouts, NULL);
 }
-                         
+
 
 /**
  * Calcualte cmac from master in @a ss.
@@ -1076,45 +1063,49 @@ static void
 calculate_cmac (struct SharedSecret *ss)
 {
   GNUNET_CRYPTO_hkdf (&ss->cmac,
-                     sizeof (ss->cmac),
-                     GCRY_MD_SHA512,
-                     GCRY_MD_SHA256,
-                     "CMAC",
-                     strlen ("CMAC"),
-                     &ss->master,
-                     sizeof (ss->master),
-                     "UDP-CMAC",
-                     strlen ("UDP-CMAC"),
-                     NULL, 0);
+                      sizeof (ss->cmac),
+                      GCRY_MD_SHA512,
+                      GCRY_MD_SHA256,
+                      "CMAC",
+                      strlen ("CMAC"),
+                      &ss->master,
+                      sizeof (ss->master),
+                      "UDP-CMAC",
+                      strlen ("UDP-CMAC"),
+                      NULL,
+                      0);
 }
 
 
 /**
  * We received @a plaintext_len bytes of @a plaintext from a @a sender.
- * Pass it on to CORE.  
+ * Pass it on to CORE.
  *
  * @param queue the queue that received the plaintext
  * @param plaintext the plaintext that was received
  * @param plaintext_len number of bytes of plaintext received
- */ 
+ */
 static void
 pass_plaintext_to_core (struct SenderAddress *sender,
-                       const void *plaintext,
-                       size_t plaintext_len)
+                        const void *plaintext,
+                        size_t plaintext_len)
 {
   const struct GNUNET_MessageHeader *hdr = plaintext;
 
   while (ntohs (hdr->size) < plaintext_len)
   {
     GNUNET_STATISTICS_update (stats,
-                             "# bytes given to core",
-                             ntohs (hdr->size),
-                             GNUNET_NO);
-    (void) GNUNET_TRANSPORT_communicator_receive (ch,
-                                                 &sender->target,
-                                                 hdr,
-                                                 NULL /* no flow control possible */,
-                                                 NULL);
+                              "# bytes given to core",
+                              ntohs (hdr->size),
+                              GNUNET_NO);
+    (void)
+      GNUNET_TRANSPORT_communicator_receive (ch,
+                                             &sender->target,
+                                             hdr,
+                                             ADDRESS_VALIDITY_PERIOD,
+                                             NULL /* no flow control possible */
+                                             ,
+                                             NULL);
     /* move on to next message, if any */
     plaintext_len -= ntohs (hdr->size);
     if (plaintext_len < sizeof (*hdr))
@@ -1122,9 +1113,9 @@ pass_plaintext_to_core (struct SenderAddress *sender,
     hdr = plaintext + ntohs (hdr->size);
   }
   GNUNET_STATISTICS_update (stats,
-                           "# bytes padding discarded",
-                           plaintext_len,
-                           GNUNET_NO);
+                            "# bytes padding discarded",
+                            plaintext_len,
+                            GNUNET_NO);
 }
 
 
@@ -1138,31 +1129,24 @@ pass_plaintext_to_core (struct SenderAddress *sender,
  */
 static void
 setup_cipher (const struct GNUNET_HashCode *msec,
-             uint32_t serial,
-             gcry_cipher_hd_t *cipher)
+              uint32_t serial,
+              gcry_cipher_hd_t *cipher)
 {
   char key[AES_KEY_SIZE];
   char iv[AES_IV_SIZE];
 
   gcry_cipher_open (cipher,
-                   GCRY_CIPHER_AES256 /* low level: go for speed */,
-                   GCRY_CIPHER_MODE_GCM,
-                   0 /* flags */);
-  get_iv_key (msec,
-             serial,
-             key,
-             iv);
-  gcry_cipher_setkey (*cipher,
-                     key,
-                     sizeof (key));
-  gcry_cipher_setiv (*cipher,
-                    iv,
-                    sizeof (iv));
+                    GCRY_CIPHER_AES256 /* low level: go for speed */,
+                    GCRY_CIPHER_MODE_GCM,
+                    0 /* flags */);
+  get_iv_key (msec, serial, key, iv);
+  gcry_cipher_setkey (*cipher, key, sizeof (key));
+  gcry_cipher_setiv (*cipher, iv, sizeof (iv));
 }
 
 
 /**
- * Try to decrypt @a buf using shared secret @a ss and key/iv 
+ * Try to decrypt @a buf using shared secret @a ss and key/iv
  * derived using @a serial.
  *
  * @param ss shared secret
@@ -1175,33 +1159,25 @@ setup_cipher (const struct GNUNET_HashCode *msec,
  */
 static int
 try_decrypt (const struct SharedSecret *ss,
-            const char tag[GCM_TAG_SIZE],
-            uint32_t serial,
-            const char *in_buf,
-            size_t in_buf_size,
-            char *out_buf)
+             const char tag[GCM_TAG_SIZE],
+             uint32_t serial,
+             const char *in_buf,
+             size_t in_buf_size,
+             char *out_buf)
 {
   gcry_cipher_hd_t cipher;
 
-  setup_cipher (&ss->master,
-               serial,
-               &cipher);
-  GNUNET_assert (0 ==
-                gcry_cipher_decrypt (cipher,
-                                     out_buf,
-                                     in_buf_size,
-                                     in_buf,
-                                     in_buf_size));
-  if (0 !=
-      gcry_cipher_checktag (cipher,
-                           tag,
-                           GCM_TAG_SIZE))
+  setup_cipher (&ss->master, serial, &cipher);
+  GNUNET_assert (
+    0 ==
+    gcry_cipher_decrypt (cipher, out_buf, in_buf_size, in_buf, in_buf_size));
+  if (0 != gcry_cipher_checktag (cipher, tag, GCM_TAG_SIZE))
   {
     gcry_cipher_close (cipher);
     GNUNET_STATISTICS_update (stats,
-                             "# AEAD authentication failures",
-                             1,
-                             GNUNET_NO);
+                              "# AEAD authentication failures",
+                              1,
+                              GNUNET_NO);
     return GNUNET_SYSERR;
   }
   gcry_cipher_close (cipher);
@@ -1221,9 +1197,7 @@ setup_shared_secret_dec (const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral)
   struct SharedSecret *ss;
 
   ss = GNUNET_new (struct SharedSecret);
-  GNUNET_CRYPTO_eddsa_ecdh (my_private_key,
-                           ephemeral,
-                           &ss->master);
+  GNUNET_CRYPTO_eddsa_ecdh (my_private_key, ephemeral, &ss->master);
   return ss;
 }
 
@@ -1237,28 +1211,34 @@ setup_shared_secret_dec (const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral)
  */
 static struct SharedSecret *
 setup_shared_secret_enc (const struct GNUNET_CRYPTO_EcdhePrivateKey *ephemeral,
-                        struct ReceiverAddress *receiver)
+                         struct ReceiverAddress *receiver)
 {
   struct SharedSecret *ss;
 
   ss = GNUNET_new (struct SharedSecret);
   GNUNET_CRYPTO_ecdh_eddsa (ephemeral,
-                           &receiver->target.public_key,
-                           &ss->master);
+                            &receiver->target.public_key,
+                            &ss->master);
   calculate_cmac (ss);
   ss->receiver = receiver;
-  GNUNET_CONTAINER_DLL_insert (receiver->ss_head,
-                              receiver->ss_tail,
-                              ss);
+  GNUNET_CONTAINER_DLL_insert (receiver->ss_head, receiver->ss_tail, ss);
   receiver->num_secrets++;
-  GNUNET_STATISTICS_update (stats,
-                           "# Secrets active",
-                           1,
-                           GNUNET_NO);
+  GNUNET_STATISTICS_update (stats, "# Secrets active", 1, GNUNET_NO);
   return ss;
 }
 
 
+/**
+ * Setup the MQ for the @a receiver.  If a queue exists,
+ * the existing one is destroyed.  Then the MTU is
+ * recalculated and a fresh queue is initialized.
+ *
+ * @param receiver receiver to setup MQ for
+ */
+static void
+setup_receiver_mq (struct ReceiverAddress *receiver);
+
+
 /**
  * We received an ACK for @a pid. Check if it is for
  * the receiver in @a value and if so, handle it and
@@ -1270,41 +1250,32 @@ setup_shared_secret_enc (const struct GNUNET_CRYPTO_EcdhePrivateKey *ephemeral,
  * @return #GNUNET_YES to continue to iterate
  */
 static int
-handle_ack (void *cls,
-           const struct GNUNET_PeerIdentity *pid,
-           void *value)
+handle_ack (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 {
   const struct UDPAck *ack = cls;
   struct ReceiverAddress *receiver = value;
 
   (void) pid;
-  for (struct SharedSecret *ss = receiver->ss_head;
-       NULL != ss;
-       ss = ss->next)
+  for (struct SharedSecret *ss = receiver->ss_head; NULL != ss; ss = ss->next)
   {
-    if (0 == memcmp (&ack->cmac,
-                    &ss->cmac,
-                    sizeof (struct GNUNET_HashCode)))
+    if (0 == memcmp (&ack->cmac, &ss->cmac, sizeof (struct GNUNET_HashCode)))
     {
       uint32_t allowed;
-      
+
       allowed = ntohl (ack->sequence_max);
-                           
+
       if (allowed > ss->sequence_allowed)
       {
-       if (0 == receiver->acks_available)
-       {
-         /* FIXME: update MTU / MQ of 'receiver'! */
-       }
-       receiver->acks_available += (allowed - ss->sequence_allowed);
-       ss->sequence_allowed = allowed;
-       /* move ss to head to avoid discarding it anytime soon! */
-       GNUNET_CONTAINER_DLL_remove (receiver->ss_head,
-                                    receiver->ss_tail,
-                                    ss);
-       GNUNET_CONTAINER_DLL_insert (receiver->ss_head,
-                                    receiver->ss_tail,
-                                    ss);
+        receiver->acks_available += (allowed - ss->sequence_allowed);
+        if ((allowed - ss->sequence_allowed) == receiver->acks_available)
+        {
+          /* we just incremented from zero => MTU change! */
+          setup_receiver_mq (receiver);
+        }
+        ss->sequence_allowed = allowed;
+        /* move ss to head to avoid discarding it anytime soon! */
+        GNUNET_CONTAINER_DLL_remove (receiver->ss_head, receiver->ss_tail, ss);
+        GNUNET_CONTAINER_DLL_insert (receiver->ss_head, receiver->ss_tail, ss);
       }
       return GNUNET_NO;
     }
@@ -1320,16 +1291,15 @@ handle_ack (void *cls,
  * @param sender peer to process inbound plaintext for
  * @param buf buffer we received
  * @param buf_size number of bytes in @a buf
- */ 
+ */
 static void
 try_handle_plaintext (struct SenderAddress *sender,
-                     const void *buf,
-                     size_t buf_size)
+                      const void *buf,
+                      size_t buf_size)
 {
-  const struct GNUNET_MessageHeader *hdr
-    = (const struct GNUNET_MessageHeader *) buf;
-  const struct UDPAck *ack
-    = (const struct UDPAck *) buf;
+  const struct GNUNET_MessageHeader *hdr =
+    (const struct GNUNET_MessageHeader *) buf;
+  const struct UDPAck *ack = (const struct UDPAck *) buf;
   uint16_t type;
 
   if (sizeof (*hdr) > buf_size)
@@ -1342,23 +1312,19 @@ try_handle_plaintext (struct SenderAddress *sender,
   case GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_ACK:
     /* lookup master secret by 'cmac', then update sequence_max */
     GNUNET_CONTAINER_multipeermap_get_multiple (receivers,
-                                               &sender->target,
-                                               &handle_ack,
-                                               (void *) ack);
+                                                &sender->target,
+                                                &handle_ack,
+                                                (void *) ack);
     /* There could be more messages after the ACK, handle those as well */
     buf += ntohs (hdr->size);
     buf_size -= ntohs (hdr->size);
-    pass_plaintext_to_core (sender,
-                           buf,
-                           buf_size);
+    pass_plaintext_to_core (sender, buf, buf_size);
     break;
   case GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_PAD:
     /* skip padding */
     break;
   default:
-    pass_plaintext_to_core (sender,
-                           buf,
-                           buf_size);
+    pass_plaintext_to_core (sender, buf, buf_size);
   }
 }
 
@@ -1376,24 +1342,24 @@ consider_ss_ack (struct SharedSecret *ss)
 {
   GNUNET_assert (NULL != ss->sender);
   /* drop ancient KeyCacheEntries */
-  while ( (NULL != ss->kce_head) &&
-         (MAX_SQN_DELTA < ss->kce_head->sequence_number - ss->kce_tail->sequence_number) )
+  while ((NULL != ss->kce_head) &&
+         (MAX_SQN_DELTA <
+          ss->kce_head->sequence_number - ss->kce_tail->sequence_number))
     kce_destroy (ss->kce_tail);
   if (ss->active_kce_count < KCN_THRESHOLD)
   {
     struct UDPAck ack;
 
     while (ss->active_kce_count < KCN_TARGET)
-      kce_generate (ss,
-                   ++ss->sequence_allowed);
+      kce_generate (ss, ++ss->sequence_allowed);
     ack.header.type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_ACK);
     ack.header.size = htons (sizeof (ack));
     ack.sequence_max = htonl (ss->sequence_allowed);
     ack.cmac = ss->cmac;
     GNUNET_TRANSPORT_communicator_notify (ch,
-                                         &ss->sender->target,
-                                         COMMUNICATOR_ADDRESS_PREFIX,
-                                         &ack.header);
+                                          &ss->sender->target,
+                                          COMMUNICATOR_ADDRESS_PREFIX,
+                                          &ack.header);
   }
 }
 
@@ -1404,39 +1370,36 @@ consider_ss_ack (struct SharedSecret *ss)
  * @param box the data we received
  * @param box_len number of bytes in @a box
  * @param kce key index to decrypt @a box
- */ 
+ */
 static void
 decrypt_box (const struct UDPBox *box,
-            size_t box_len,
-            struct KeyCacheEntry *kce)
+             size_t box_len,
+             struct KeyCacheEntry *kce)
 {
   struct SharedSecret *ss = kce->ss;
   char out_buf[box_len - sizeof (*box)];
 
   GNUNET_assert (NULL != ss->sender);
-  if (GNUNET_OK !=
-      try_decrypt (ss,
-                  box->gcm_tag,
-                  kce->sequence_number,
-                  (const char *) &box[1],
-                  sizeof (out_buf),
-                  out_buf))
+  if (GNUNET_OK != try_decrypt (ss,
+                                box->gcm_tag,
+                                kce->sequence_number,
+                                (const char *) &box[1],
+                                sizeof (out_buf),
+                                out_buf))
   {
     GNUNET_STATISTICS_update (stats,
-                             "# Decryption failures with valid KCE",
-                             1,
-                             GNUNET_NO);
+                              "# Decryption failures with valid KCE",
+                              1,
+                              GNUNET_NO);
     kce_destroy (kce);
     return;
   }
   kce_destroy (kce);
   GNUNET_STATISTICS_update (stats,
-                           "# bytes decrypted with BOX",
-                           sizeof (out_buf),
-                           GNUNET_NO);
-  try_handle_plaintext (ss->sender,
-                       out_buf,
-                       sizeof (out_buf));
+                            "# bytes decrypted with BOX",
+                            sizeof (out_buf),
+                            GNUNET_NO);
+  try_handle_plaintext (ss->sender, out_buf, sizeof (out_buf));
   consider_ss_ack (ss);
 }
 
@@ -1473,16 +1436,14 @@ struct SearchContext
  */
 static int
 find_sender_by_address (void *cls,
-                       const struct GNUNET_PeerIdentity *key,
-                       void *value)
+                        const struct GNUNET_PeerIdentity *key,
+                        void *value)
 {
   struct SearchContext *sc = cls;
   struct SenderAddress *sender = value;
 
-  if ( (sender->address_len == sc->address_len) &&
-       (0 == memcmp (sender->address,
-                    sc->address,
-                    sender->address_len)) )
+  if ((sender->address_len == sc->address_len) &&
+      (0 == memcmp (sender->address, sc->address, sender->address_len)))
   {
     sc->sender = sender;
     return GNUNET_NO; /* stop iterating! */
@@ -1497,27 +1458,25 @@ find_sender_by_address (void *cls,
  * if one does not yet exist for @a address.
  *
  * @param target peer to generate address for
- * @param address target address 
+ * @param address target address
  * @param address_len number of bytes in @a address
  * @return data structure to keep track of key material for
  *         decrypting data from @a target
  */
 static struct SenderAddress *
 setup_sender (const struct GNUNET_PeerIdentity *target,
-             const struct sockaddr *address,
-             socklen_t address_len)
+              const struct sockaddr *address,
+              socklen_t address_len)
 {
   struct SenderAddress *sender;
-  struct SearchContext sc = {
-    .address = address,
-    .address_len = address_len,
-    .sender = NULL
-  };
+  struct SearchContext sc = {.address = address,
+                             .address_len = address_len,
+                             .sender = NULL};
 
   GNUNET_CONTAINER_multipeermap_get_multiple (senders,
-                                             target,
-                                             &find_sender_by_address,
-                                             &sc);
+                                              target,
+                                              &find_sender_by_address,
+                                              &sc);
   if (NULL != sc.sender)
   {
     reschedule_sender_timeout (sc.sender);
@@ -1525,28 +1484,25 @@ setup_sender (const struct GNUNET_PeerIdentity *target,
   }
   sender = GNUNET_new (struct SenderAddress);
   sender->target = *target;
-  sender->address = GNUNET_memdup (address,
-                                  address_len);
+  sender->address = GNUNET_memdup (address, address_len);
   sender->address_len = address_len;
-  (void) GNUNET_CONTAINER_multipeermap_put (senders,
-                                           &sender->target,
-                                           sender,
-                                           GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+  (void) GNUNET_CONTAINER_multipeermap_put (
+    senders,
+    &sender->target,
+    sender,
+    GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
   GNUNET_STATISTICS_set (stats,
-                        "# senders active",
-                        GNUNET_CONTAINER_multipeermap_size (receivers),
-                        GNUNET_NO);
-  sender->timeout
-    GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
+                         "# senders active",
+                         GNUNET_CONTAINER_multipeermap_size (receivers),
+                         GNUNET_NO);
+  sender->timeout =
+    GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
   sender->hn = GNUNET_CONTAINER_heap_insert (senders_heap,
-                                            sender,
-                                            sender->timeout.abs_value_us);
-  sender->nt = GNUNET_NT_scanner_get_type (is,
-                                          address,
-                                          address_len);
+                                             sender,
+                                             sender->timeout.abs_value_us);
+  sender->nt = GNUNET_NT_scanner_get_type (is, address, address_len);
   if (NULL == timeout_task)
-    timeout_task = GNUNET_SCHEDULER_add_now (&check_timeouts,
-                                            NULL);
+    timeout_task = GNUNET_SCHEDULER_add_now (&check_timeouts, NULL);
   return sender;
 }
 
@@ -1560,10 +1516,10 @@ setup_sender (const struct GNUNET_PeerIdentity *target,
  */
 static int
 verify_confirmation (const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral,
-                    const struct UDPConfirmation *uc)
+                     const struct UDPConfirmation *uc)
 {
   struct UdpHandshakeSignature uhs;
-                       
+
   uhs.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_UDP_HANDSHAKE);
   uhs.purpose.size = htonl (sizeof (uhs));
   uhs.sender = uc->sender;
@@ -1571,14 +1527,49 @@ verify_confirmation (const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral,
   uhs.ephemeral = *ephemeral;
   uhs.monotonic_time = uc->monotonic_time;
   return GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_COMMUNICATOR_UDP_HANDSHAKE,
-                                    &uhs.purpose,
-                                    &uc->sender_sig,
-                                    &uc->sender.public_key);
+                                     &uhs.purpose,
+                                     &uc->sender_sig,
+                                     &uc->sender.public_key);
+}
+
+
+/**
+ * Converts @a address to the address string format used by this
+ * communicator in HELLOs.
+ *
+ * @param address the address to convert, must be AF_INET or AF_INET6.
+ * @param address_len number of bytes in @a address
+ * @return string representation of @a address
+ */
+static char *
+sockaddr_to_udpaddr_string (const struct sockaddr *address,
+                            socklen_t address_len)
+{
+  char *ret;
+
+  switch (address->sa_family)
+  {
+  case AF_INET:
+    GNUNET_asprintf (&ret,
+                     "%s-%s",
+                     COMMUNICATOR_ADDRESS_PREFIX,
+                     GNUNET_a2s (address, address_len));
+    break;
+  case AF_INET6:
+    GNUNET_asprintf (&ret,
+                     "%s-%s",
+                     COMMUNICATOR_ADDRESS_PREFIX,
+                     GNUNET_a2s (address, address_len));
+    break;
+  default:
+    GNUNET_assert (0);
+  }
+  return ret;
 }
 
 
 /**
- * Socket read task. 
+ * Socket read task.
  *
  * @param cls NULL
  */
@@ -1591,20 +1582,18 @@ sock_read (void *cls)
   ssize_t rcvd;
 
   (void) cls;
-  read_task
-      = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
-                                      udp_sock,
-                                      &sock_read,
-                                      NULL);
+  read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                             udp_sock,
+                                             &sock_read,
+                                             NULL);
   rcvd = GNUNET_NETWORK_socket_recvfrom (udp_sock,
-                                        buf,
-                                        sizeof (buf),
-                                        (struct sockaddr *) &sa,
-                                        &salen);
+                                         buf,
+                                         sizeof (buf),
+                                         (struct sockaddr *) &sa,
+                                         &salen);
   if (-1 == rcvd)
   {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG,
-                        "recv");
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "recv");
     return;
   }
 
@@ -1615,13 +1604,10 @@ sock_read (void *cls)
     struct KeyCacheEntry *kce;
 
     box = (const struct UDPBox *) buf;
-    kce = GNUNET_CONTAINER_multishortmap_get (key_cache,
-                                             &box->kid);
+    kce = GNUNET_CONTAINER_multishortmap_get (key_cache, &box->kid);
     if (NULL != kce)
     {
-      decrypt_box (box,
-                  (size_t) rcvd,
-                  kce);
+      decrypt_box (box, (size_t) rcvd, kce);
       return;
     }
   }
@@ -1636,34 +1622,45 @@ sock_read (void *cls)
     uhs.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_UDP_BROADCAST);
     uhs.purpose.size = htonl (sizeof (uhs));
     uhs.sender = ub->sender;
-    GNUNET_CRYPTO_hash (&sa,
-                       salen,
-                       &uhs.h_address);
+    GNUNET_CRYPTO_hash (&sa, salen, &uhs.h_address);
     if (GNUNET_OK ==
-       GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_COMMUNICATOR_UDP_BROADCAST,
-                                   &uhs.purpose,
-                                   &ub->sender_sig,
-                                   &ub->sender.public_key))
+        GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_COMMUNICATOR_UDP_BROADCAST,
+                                    &uhs.purpose,
+                                    &ub->sender_sig,
+                                    &ub->sender.public_key))
     {
-      GNUNET_STATISTICS_update (stats,
-                               "# broadcasts received",
-                               1,
-                               GNUNET_NO);
-      // FIXME: we effectively just got a HELLO!
-      // trigger verification NOW!
+      char *addr_s;
+      struct GNUNET_TIME_Absolute expiration;
+      enum GNUNET_NetworkType nt;
+
+      addr_s =
+        sockaddr_to_udpaddr_string ((const struct sockaddr *) &sa, salen);
+      GNUNET_STATISTICS_update (stats, "# broadcasts received", 1, GNUNET_NO);
+      /* expire at the broadcast frequency, as then we'll get the next one
+       * anyway */
+      expiration = GNUNET_TIME_relative_to_absolute (BROADCAST_FREQUENCY);
+      /* use our own mechanism to determine network type */
+      nt =
+        GNUNET_NT_scanner_get_type (is, (const struct sockaddr *) &sa, salen);
+      GNUNET_TRANSPORT_application_validate (ah,
+                                             &ub->sender,
+                                             expiration,
+                                             nt,
+                                             addr_s);
+      GNUNET_free (addr_s);
       return;
     }
     /* continue with KX, mostly for statistics... */
   }
-  
+
 
   /* finally, test if it is a KX */
   if (rcvd < sizeof (struct UDPConfirmation) + sizeof (struct InitialKX))
   {
     GNUNET_STATISTICS_update (stats,
-                             "# messages dropped (no kid, too small for KX)",
-                             1,
-                             GNUNET_NO);
+                              "# messages dropped (no kid, too small for KX)",
+                              1,
+                              GNUNET_NO);
     return;
   }
 
@@ -1676,54 +1673,43 @@ sock_read (void *cls)
 
     kx = (const struct InitialKX *) buf;
     ss = setup_shared_secret_dec (&kx->ephemeral);
-    if (GNUNET_OK !=
-       try_decrypt (ss,
-                    kx->gcm_tag,
-                    0,
-                    &buf[sizeof (*kx)],
-                    sizeof (pbuf),
-                    pbuf))
+    if (GNUNET_OK != try_decrypt (ss,
+                                  kx->gcm_tag,
+                                  0,
+                                  &buf[sizeof (*kx)],
+                                  sizeof (pbuf),
+                                  pbuf))
     {
       GNUNET_free (ss);
-      GNUNET_STATISTICS_update (stats,
-                               "# messages dropped (no kid, AEAD decryption failed)",
-                               1,
-                               GNUNET_NO);
+      GNUNET_STATISTICS_update (
+        stats,
+        "# messages dropped (no kid, AEAD decryption failed)",
+        1,
+        GNUNET_NO);
       return;
     }
     uc = (const struct UDPConfirmation *) pbuf;
-    if (GNUNET_OK !=
-       verify_confirmation (&kx->ephemeral,
-                            uc))
+    if (GNUNET_OK != verify_confirmation (&kx->ephemeral, uc))
     {
       GNUNET_break_op (0);
       GNUNET_free (ss);
       GNUNET_STATISTICS_update (stats,
-                               "# messages dropped (sender signature invalid)",
-                               1,
-                               GNUNET_NO);
+                                "# messages dropped (sender signature invalid)",
+                                1,
+                                GNUNET_NO);
       return;
     }
     calculate_cmac (ss);
-    sender = setup_sender (&uc->sender,
-                          (const struct sockaddr *) &sa,
-                          salen);
+    sender = setup_sender (&uc->sender, (const struct sockaddr *) &sa, salen);
     ss->sender = sender;
-    GNUNET_CONTAINER_DLL_insert (sender->ss_head,
-                                sender->ss_tail,
-                                ss);
+    GNUNET_CONTAINER_DLL_insert (sender->ss_head, sender->ss_tail, ss);
     sender->num_secrets++;
+    GNUNET_STATISTICS_update (stats, "# Secrets active", 1, GNUNET_NO);
     GNUNET_STATISTICS_update (stats,
-                             "# Secrets active",
-                             1,
-                             GNUNET_NO);
-    GNUNET_STATISTICS_update (stats,
-                             "# messages decrypted without BOX",
-                             1,
-                             GNUNET_NO);
-    try_handle_plaintext (sender,
-                         &uc[1],
-                         sizeof (pbuf) - sizeof (*uc));
+                              "# messages decrypted without BOX",
+                              1,
+                              GNUNET_NO);
+    try_handle_plaintext (sender, &uc[1], sizeof (pbuf) - sizeof (*uc));
     consider_ss_ack (ss);
     if (sender->num_secrets > MAX_SECRETS)
       secret_destroy (sender->ss_tail);
@@ -1739,37 +1725,32 @@ sock_read (void *cls)
  * @return converted bindto specification
  */
 static struct sockaddr *
-udp_address_to_sockaddr (const char *bindto,
-                        socklen_t *sock_len)
+udp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
 {
   struct sockaddr *in;
   unsigned int port;
   char dummy[2];
   char *colon;
   char *cp;
-  
-  if (1 == SSCANF (bindto,
-                  "%u%1s",
-                  &port,
-                  dummy))
+
+  if (1 == SSCANF (bindto, "%u%1s", &port, dummy))
   {
     /* interpreting value as just a PORT number */
     if (port > UINT16_MAX)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 "BINDTO specification `%s' invalid: value too large for port\n",
-                 bindto);
+                  "BINDTO specification `%s' invalid: value too large for port\n",
+                  bindto);
       return NULL;
     }
-    /* FIXME #V6: add test to util/ for IPv6 availability,
-       and depending on the result, go directly for v4-only */
-    if (GNUNET_YES ==
-       GNUNET_CONFIGURATION_get_value_yesno (cfg,
-                                             COMMUNICATOR_CONFIG_SECTION,
-                                             "DISABLE_V6"))
+    if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
+        (GNUNET_YES ==
+         GNUNET_CONFIGURATION_get_value_yesno (cfg,
+                                               COMMUNICATOR_CONFIG_SECTION,
+                                               "DISABLE_V6")))
     {
       struct sockaddr_in *i4;
-      
+
       i4 = GNUNET_malloc (sizeof (struct sockaddr_in));
       i4->sin_family = AF_INET;
       i4->sin_port = htons ((uint16_t) port);
@@ -1779,7 +1760,7 @@ udp_address_to_sockaddr (const char *bindto,
     else
     {
       struct sockaddr_in6 *i6;
-      
+
       i6 = GNUNET_malloc (sizeof (struct sockaddr_in6));
       i6->sin6_family = AF_INET6;
       i6->sin6_port = htons ((uint16_t) port);
@@ -1795,26 +1776,24 @@ udp_address_to_sockaddr (const char *bindto,
     /* interpet value after colon as port */
     *colon = '\0';
     colon++;
-    if (1 == SSCANF (colon,
-                    "%u%1s",
-                    &port,
-                    dummy))
+    if (1 == SSCANF (colon, "%u%1s", &port, dummy))
     {
       /* interpreting value as just a PORT number */
       if (port > UINT16_MAX)
       {
-       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                   "BINDTO specification `%s' invalid: value too large for port\n",
-                   bindto);
-       GNUNET_free (cp);
-       return NULL;
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "BINDTO specification `%s' invalid: value too large for port\n",
+                    bindto);
+        GNUNET_free (cp);
+        return NULL;
       }
     }
     else
     {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 "BINDTO specification `%s' invalid: last ':' not followed by number\n",
-                 bindto);
+      GNUNET_log (
+        GNUNET_ERROR_TYPE_ERROR,
+        "BINDTO specification `%s' invalid: last ':' not followed by number\n",
+        bindto);
       GNUNET_free (cp);
       return NULL;
     }
@@ -1828,13 +1807,10 @@ udp_address_to_sockaddr (const char *bindto,
     /* try IPv4 */
     struct sockaddr_in v4;
 
-    if (1 == inet_pton (AF_INET,
-                       cp,
-                       &v4))
+    if (1 == inet_pton (AF_INET, cp, &v4))
     {
       v4.sin_port = htons ((uint16_t) port);
-      in = GNUNET_memdup (&v4,
-                         sizeof (v4));
+      in = GNUNET_memdup (&v4, sizeof (v4));
       *sock_len = sizeof (v4);
       GNUNET_free (cp);
       return in;
@@ -1846,19 +1822,15 @@ udp_address_to_sockaddr (const char *bindto,
     const char *start;
 
     start = cp;
-    if ( ('[' == *cp) &&
-        (']' == cp[strlen (cp)-1]) )
+    if (('[' == *cp) && (']' == cp[strlen (cp) - 1]))
     {
       start++; /* skip over '[' */
-      cp[strlen (cp) -1] = '\0'; /* eat ']' */
+      cp[strlen (cp) - 1] = '\0'; /* eat ']' */
     }
-    if (1 == inet_pton (AF_INET6,
-                       start,
-                       &v6))
+    if (1 == inet_pton (AF_INET6, start, &v6))
     {
       v6.sin6_port = htons ((uint16_t) port);
-      in = GNUNET_memdup (&v6,
-                         sizeof (v6));
+      in = GNUNET_memdup (&v6, sizeof (v6));
       *sock_len = sizeof (v6);
       GNUNET_free (cp);
       return in;
@@ -1878,32 +1850,22 @@ udp_address_to_sockaddr (const char *bindto,
  * @param pad_size number of bytes of padding to append
  */
 static void
-do_pad (gcry_cipher_hd_t out_cipher,
-       char *dgram,
-       size_t pad_size)
+do_pad (gcry_cipher_hd_t out_cipher, char *dgram, size_t pad_size)
 {
   char pad[pad_size];
 
-  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
-                             pad,
-                             sizeof (pad));
+  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, pad, sizeof (pad));
   if (sizeof (pad) > sizeof (struct GNUNET_MessageHeader))
   {
-    struct GNUNET_MessageHeader hdr = {
-      .size = htons (sizeof (pad)),
-      .type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_PAD)
-    };
-    
-    memcpy (pad,
-           &hdr,
-           sizeof (hdr));
-  }
-  GNUNET_assert (0 ==
-                gcry_cipher_encrypt (out_cipher,
-                                     dgram,
-                                     sizeof (pad),
-                                     pad,
-                                     sizeof (pad)));
+    struct GNUNET_MessageHeader hdr =
+      {.size = htons (sizeof (pad)),
+       .type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_PAD)};
+
+    memcpy (pad, &hdr, sizeof (hdr));
+  }
+  GNUNET_assert (
+    0 ==
+    gcry_cipher_encrypt (out_cipher, dgram, sizeof (pad), pad, sizeof (pad)));
 }
 
 
@@ -1917,8 +1879,8 @@ do_pad (gcry_cipher_hd_t out_cipher,
  */
 static void
 mq_send (struct GNUNET_MQ_Handle *mq,
-        const struct GNUNET_MessageHeader *msg,
-        void *impl_state)
+         const struct GNUNET_MessageHeader *msg,
+         void *impl_state)
 {
   struct ReceiverAddress *receiver = impl_state;
   uint16_t msize = ntohs (msg->size);
@@ -1931,7 +1893,7 @@ mq_send (struct GNUNET_MQ_Handle *mq,
     return;
   }
   reschedule_receiver_timeout (receiver);
-  
+
   if (0 == receiver->acks_available)
   {
     /* use KX encryption method */
@@ -1939,84 +1901,61 @@ mq_send (struct GNUNET_MQ_Handle *mq,
     struct UDPConfirmation uc;
     struct InitialKX kx;
     struct GNUNET_CRYPTO_EcdhePrivateKey epriv;
-    char dgram[receiver->mtu +
-              sizeof (uc) +
-              sizeof (kx)];
+    char dgram[receiver->mtu + sizeof (uc) + sizeof (kx)];
     size_t dpos;
     gcry_cipher_hd_t out_cipher;
     struct SharedSecret *ss;
 
     /* setup key material */
-    GNUNET_assert (GNUNET_OK ==
-                  GNUNET_CRYPTO_ecdhe_key_create2 (&epriv));
-
-    ss = setup_shared_secret_enc (&epriv,
-                                 receiver);
-    setup_cipher (&ss->master,
-                 0,
-                 &out_cipher);
+    GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdhe_key_create2 (&epriv));
+
+    ss = setup_shared_secret_enc (&epriv, receiver);
+    setup_cipher (&ss->master, 0, &out_cipher);
     /* compute 'uc' */
     uc.sender = my_identity;
-    uc.monotonic_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg));
+    uc.monotonic_time =
+      GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg));
     uhs.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_UDP_HANDSHAKE);
     uhs.purpose.size = htonl (sizeof (uhs));
     uhs.sender = my_identity;
     uhs.receiver = receiver->target;
-    GNUNET_CRYPTO_ecdhe_key_get_public (&epriv,
-                                       &uhs.ephemeral);
+    GNUNET_CRYPTO_ecdhe_key_get_public (&epriv, &uhs.ephemeral);
     uhs.monotonic_time = uc.monotonic_time;
-    GNUNET_assert (GNUNET_OK ==
-                  GNUNET_CRYPTO_eddsa_sign (my_private_key,
-                                            &uhs.purpose,
-                                            &uc.sender_sig));
+    GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (my_private_key,
+                                                          &uhs.purpose,
+                                                          &uc.sender_sig));
     /* Leave space for kx */
     dpos = sizeof (struct GNUNET_CRYPTO_EcdhePublicKey);
     /* Append encrypted uc to dgram */
-    GNUNET_assert (0 ==
-                  gcry_cipher_encrypt (out_cipher,
-                                       &dgram[dpos],
-                                       sizeof (uc),
-                                       &uc,
-                                       sizeof (uc)));
+    GNUNET_assert (0 == gcry_cipher_encrypt (out_cipher,
+                                             &dgram[dpos],
+                                             sizeof (uc),
+                                             &uc,
+                                             sizeof (uc)));
     dpos += sizeof (uc);
     /* Append encrypted payload to dgram */
-    GNUNET_assert (0 ==
-                  gcry_cipher_encrypt (out_cipher,
-                                       &dgram[dpos],
-                                       msize,
-                                       msg,
-                                       msize));
+    GNUNET_assert (
+      0 == gcry_cipher_encrypt (out_cipher, &dgram[dpos], msize, msg, msize));
     dpos += msize;
-    do_pad (out_cipher,
-           &dgram[dpos],
-           sizeof (dgram) - dpos);
+    do_pad (out_cipher, &dgram[dpos], sizeof (dgram) - dpos);
     /* Datagram starts with kx */
     kx.ephemeral = uhs.ephemeral;
-    GNUNET_assert (0 ==
-                  gcry_cipher_gettag (out_cipher,
-                                      kx.gcm_tag,
-                                      sizeof (kx.gcm_tag)));
+    GNUNET_assert (
+      0 == gcry_cipher_gettag (out_cipher, kx.gcm_tag, sizeof (kx.gcm_tag)));
     gcry_cipher_close (out_cipher);
-    memcpy (dgram,
-           &kx,
-           sizeof (kx));
-    if (-1 ==
-       GNUNET_NETWORK_socket_sendto (udp_sock,
-                                     dgram,
-                                     sizeof (dgram),
-                                     receiver->address,
-                                     receiver->address_len))
-      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
-                          "send");
+    memcpy (dgram, &kx, sizeof (kx));
+    if (-1 == GNUNET_NETWORK_socket_sendto (udp_sock,
+                                            dgram,
+                                            sizeof (dgram),
+                                            receiver->address,
+                                            receiver->address_len))
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "send");
     GNUNET_MQ_impl_send_continue (mq);
     return;
   } /* End of KX encryption method */
 
-  // FIXME: add support for BOX encryption method!
   /* begin "BOX" encryption method, scan for ACKs from tail! */
-  for (struct SharedSecret *ss = receiver->ss_tail;
-       NULL != ss;
-       ss = ss->prev)
+  for (struct SharedSecret *ss = receiver->ss_tail; NULL != ss; ss = ss->prev)
   {
     if (ss->sequence_used < ss->sequence_allowed)
     {
@@ -2027,42 +1966,30 @@ mq_send (struct GNUNET_MQ_Handle *mq,
 
       box = (struct UDPBox *) dgram;
       ss->sequence_used++;
-      get_kid (&ss->master,
-              ss->sequence_used,
-              &box->kid);
-      setup_cipher (&ss->master,
-                   ss->sequence_used,
-                   &out_cipher);
+      get_kid (&ss->master, ss->sequence_used, &box->kid);
+      setup_cipher (&ss->master, ss->sequence_used, &out_cipher);
       /* Append encrypted payload to dgram */
       dpos = sizeof (struct UDPBox);
-      GNUNET_assert (0 ==
-                    gcry_cipher_encrypt (out_cipher,
-                                         &dgram[dpos],
-                                         msize,
-                                         msg,
-                                         msize));
+      GNUNET_assert (
+        0 == gcry_cipher_encrypt (out_cipher, &dgram[dpos], msize, msg, msize));
       dpos += msize;
-      do_pad (out_cipher,
-             &dgram[dpos],
-             sizeof (dgram) - dpos);
-      GNUNET_assert (0 ==
-                    gcry_cipher_gettag (out_cipher,
-                                        box->gcm_tag,
-                                        sizeof (box->gcm_tag)));
+      do_pad (out_cipher, &dgram[dpos], sizeof (dgram) - dpos);
+      GNUNET_assert (0 == gcry_cipher_gettag (out_cipher,
+                                              box->gcm_tag,
+                                              sizeof (box->gcm_tag)));
       gcry_cipher_close (out_cipher);
-      if (-1 ==
-         GNUNET_NETWORK_socket_sendto (udp_sock,
-                                       dgram,
-                                       sizeof (dgram),
-                                       receiver->address,
-                                       receiver->address_len))
-       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
-                            "send");
+      if (-1 == GNUNET_NETWORK_socket_sendto (udp_sock,
+                                              dgram,
+                                              sizeof (dgram),
+                                              receiver->address,
+                                              receiver->address_len))
+        GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "send");
       GNUNET_MQ_impl_send_continue (mq);
       receiver->acks_available--;
       if (0 == receiver->acks_available)
       {
-       /* FIXME: update MTU / MQ of 'receiver'! */
+        /* We have no more ACKs => MTU change! */
+        setup_receiver_mq (receiver);
       }
       return;
     }
@@ -2080,8 +2007,7 @@ mq_send (struct GNUNET_MQ_Handle *mq,
  * @param impl_state our `struct ReceiverAddress`
  */
 static void
-mq_destroy (struct GNUNET_MQ_Handle *mq,
-           void *impl_state)
+mq_destroy (struct GNUNET_MQ_Handle *mq, void *impl_state)
 {
   struct ReceiverAddress *receiver = impl_state;
 
@@ -2100,8 +2026,7 @@ mq_destroy (struct GNUNET_MQ_Handle *mq,
  * @param impl_state our `struct RecvierAddress`
  */
 static void
-mq_cancel (struct GNUNET_MQ_Handle *mq,
-          void *impl_state)
+mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
 {
   /* Cancellation is impossible with UDP; bail */
   GNUNET_assert (0);
@@ -2118,97 +2043,124 @@ mq_cancel (struct GNUNET_MQ_Handle *mq,
  * @param error error code
  */
 static void
-mq_error (void *cls,
-         enum GNUNET_MQ_Error error)
+mq_error (void *cls, enum GNUNET_MQ_Error error)
 {
   struct ReceiverAddress *receiver = cls;
 
   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-             "MQ error in queue to %s: %d\n",
-             GNUNET_i2s (&receiver->target),
-             (int) error);
+              "MQ error in queue to %s: %d\n",
+              GNUNET_i2s (&receiver->target),
+              (int) error);
   receiver_destroy (receiver);
 }
 
 
+/**
+ * Setup the MQ for the @a receiver.  If a queue exists,
+ * the existing one is destroyed.  Then the MTU is
+ * recalculated and a fresh queue is initialized.
+ *
+ * @param receiver receiver to setup MQ for
+ */
+static void
+setup_receiver_mq (struct ReceiverAddress *receiver)
+{
+  size_t base_mtu;
+
+  if (NULL != receiver->qh)
+  {
+    GNUNET_TRANSPORT_communicator_mq_del (receiver->qh);
+    receiver->qh = NULL;
+  }
+  GNUNET_assert (NULL == receiver->mq);
+  switch (receiver->address->sa_family)
+  {
+  case AF_INET:
+    base_mtu = 1480 /* Ethernet MTU, 1500 - Ethernet header - VLAN tag */
+               - sizeof (struct GNUNET_TUN_IPv4Header) /* 20 */
+               - sizeof (struct GNUNET_TUN_UdpHeader) /* 8 */;
+    break;
+  case AF_INET6:
+    base_mtu = 1280 /* Minimum MTU required by IPv6 */
+               - sizeof (struct GNUNET_TUN_IPv6Header) /* 40 */
+               - sizeof (struct GNUNET_TUN_UdpHeader) /* 8 */;
+    break;
+  default:
+    GNUNET_assert (0);
+    break;
+  }
+  if (0 == receiver->acks_available)
+  {
+    /* MTU based on full KX messages */
+    receiver->mtu = base_mtu - sizeof (struct InitialKX) /* 48 */
+                    - sizeof (struct UDPConfirmation); /* 104 */
+  }
+  else
+  {
+    /* MTU based on BOXed messages */
+    receiver->mtu = base_mtu - sizeof (struct UDPBox);
+  }
+  /* => Effective MTU for CORE will range from 1080 (IPv6 + KX) to
+     1404 (IPv4 + Box) bytes, depending on circumstances... */
+  receiver->mq = GNUNET_MQ_queue_for_callbacks (&mq_send,
+                                                &mq_destroy,
+                                                &mq_cancel,
+                                                receiver,
+                                                NULL,
+                                                &mq_error,
+                                                receiver);
+  receiver->qh =
+    GNUNET_TRANSPORT_communicator_mq_add (ch,
+                                          &receiver->target,
+                                          receiver->foreign_addr,
+                                          receiver->mtu,
+                                          receiver->nt,
+                                          GNUNET_TRANSPORT_CS_OUTBOUND,
+                                          receiver->mq);
+}
+
+
 /**
  * Setup a receiver for transmission.  Setup the MQ processing and
- * inform transport that the queue is ready. 
+ * inform transport that the queue is ready.
  *
- * @param 
- */ 
+ * @param target which peer are we talking to
+ * @param address address of the peer
+ * @param address_len number of bytes in @a address
+ * @return handle for the address
+ */
 static struct ReceiverAddress *
 receiver_setup (const struct GNUNET_PeerIdentity *target,
-               const struct sockaddr *address,
-               socklen_t address_len)
+                const struct sockaddr *address,
+                socklen_t address_len)
 {
   struct ReceiverAddress *receiver;
 
   receiver = GNUNET_new (struct ReceiverAddress);
-  receiver->address = GNUNET_memdup (address,
-                                    address_len);
+  receiver->address = GNUNET_memdup (address, address_len);
   receiver->address_len = address_len;
   receiver->target = *target;
-  receiver->nt = GNUNET_NT_scanner_get_type (is,
-                                            address,
-                                            address_len);
-  (void) GNUNET_CONTAINER_multipeermap_put (receivers,
-                                           &receiver->target,
-                                           receiver,
-                                           GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
-  receiver->timeout
-    = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
+  receiver->nt = GNUNET_NT_scanner_get_type (is, address, address_len);
+  (void) GNUNET_CONTAINER_multipeermap_put (
+    receivers,
+    &receiver->target,
+    receiver,
+    GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+  receiver->timeout =
+    GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
   receiver->hn = GNUNET_CONTAINER_heap_insert (receivers_heap,
-                                              receiver,
-                                              receiver->timeout.abs_value_us);
-  receiver->mq
-    = GNUNET_MQ_queue_for_callbacks (&mq_send,
-                                    &mq_destroy,
-                                    &mq_cancel,
-                                    receiver,
-                                    NULL,
-                                    &mq_error,
-                                    receiver);
-  receiver->mtu = 1200 /* FIXME: MTU OK? */;
-  if (NULL == timeout_task)
-    timeout_task = GNUNET_SCHEDULER_add_now (&check_timeouts,
-                                            NULL);
+                                               receiver,
+                                               receiver->timeout.abs_value_us);
   GNUNET_STATISTICS_set (stats,
-                        "# receivers active",
-                        GNUNET_CONTAINER_multipeermap_size (receivers),
-                        GNUNET_NO);
-  {
-    char *foreign_addr;
+                         "# receivers active",
+                         GNUNET_CONTAINER_multipeermap_size (receivers),
+                         GNUNET_NO);
+  receiver->foreign_addr =
+    sockaddr_to_udpaddr_string (receiver->address, receiver->address_len);
+  setup_receiver_mq (receiver);
 
-    switch (address->sa_family)
-    {
-    case AF_INET:
-      GNUNET_asprintf (&foreign_addr,
-                      "%s-%s",
-                      COMMUNICATOR_ADDRESS_PREFIX,
-                      GNUNET_a2s (receiver->address,
-                                  receiver->address_len));
-      break;
-    case AF_INET6:
-      GNUNET_asprintf (&foreign_addr,
-                      "%s-%s",
-                      COMMUNICATOR_ADDRESS_PREFIX,
-                      GNUNET_a2s (receiver->address,
-                                  receiver->address_len));
-      break;
-    default:
-      GNUNET_assert (0);
-    }
-    receiver->qh
-      = GNUNET_TRANSPORT_communicator_mq_add (ch,
-                                             &receiver->target,
-                                             foreign_addr,
-                                             receiver->mtu,
-                                             receiver->nt,
-                                             GNUNET_TRANSPORT_CS_OUTBOUND,
-                                             receiver->mq);
-    GNUNET_free (foreign_addr);
-  }
+  if (NULL == timeout_task)
+    timeout_task = GNUNET_SCHEDULER_add_now (&check_timeouts, NULL);
   return receiver;
 }
 
@@ -2228,33 +2180,29 @@ receiver_setup (const struct GNUNET_PeerIdentity *target,
  * @param peer identity of the other peer
  * @param address where to send the message, human-readable
  *        communicator-specific format, 0-terminated, UTF-8
- * @return #GNUNET_OK on success, #GNUNET_SYSERR if the provided address is invalid
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR if the provided address is
+ * invalid
  */
 static int
-mq_init (void *cls,
-        const struct GNUNET_PeerIdentity *peer,
-        const char *address)
+mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
 {
   struct ReceiverAddress *receiver;
   const char *path;
   struct sockaddr *in;
   socklen_t in_len;
-  
+
   if (0 != strncmp (address,
-                   COMMUNICATOR_ADDRESS_PREFIX "-",
-                   strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
+                    COMMUNICATOR_ADDRESS_PREFIX "-",
+                    strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
   {
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
   path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
-  in = udp_address_to_sockaddr (path,
-                               &in_len);  
-  receiver = receiver_setup (peer,
-                            in,
-                            in_len);
+  in = udp_address_to_sockaddr (path, &in_len);
+  receiver = receiver_setup (peer, in, in_len);
   (void) receiver;
-  return GNUNET_OK;  
+  return GNUNET_OK;
 }
 
 
@@ -2268,8 +2216,8 @@ mq_init (void *cls,
  */
 static int
 get_receiver_delete_it (void *cls,
-                       const struct GNUNET_PeerIdentity *target,
-                       void *value)
+                        const struct GNUNET_PeerIdentity *target,
+                        void *value)
 {
   struct ReceiverAddress *receiver = value;
 
@@ -2290,8 +2238,8 @@ get_receiver_delete_it (void *cls,
  */
 static int
 get_sender_delete_it (void *cls,
-                     const struct GNUNET_PeerIdentity *target,
-                     void *value)
+                      const struct GNUNET_PeerIdentity *target,
+                      void *value)
 {
   struct SenderAddress *sender = value;
 
@@ -2312,8 +2260,8 @@ do_shutdown (void *cls)
 {
   if (NULL != nat)
   {
-     GNUNET_NAT_unregister (nat);
-     nat = NULL;
+    GNUNET_NAT_unregister (nat);
+    nat = NULL;
   }
   while (NULL != bi_head)
     bi_destroy (bi_head);
@@ -2329,17 +2277,14 @@ do_shutdown (void *cls)
   }
   if (NULL != udp_sock)
   {
-    GNUNET_break (GNUNET_OK ==
-                  GNUNET_NETWORK_socket_close (udp_sock));
+    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (udp_sock));
     udp_sock = NULL;
   }
   GNUNET_CONTAINER_multipeermap_iterate (receivers,
-                                        &get_receiver_delete_it,
+                                         &get_receiver_delete_it,
                                          NULL);
   GNUNET_CONTAINER_multipeermap_destroy (receivers);
-  GNUNET_CONTAINER_multipeermap_iterate (senders,
-                                        &get_sender_delete_it,
-                                         NULL);
+  GNUNET_CONTAINER_multipeermap_iterate (senders, &get_sender_delete_it, NULL);
   GNUNET_CONTAINER_multipeermap_destroy (senders);
   GNUNET_CONTAINER_multishortmap_destroy (key_cache);
   GNUNET_CONTAINER_heap_destroy (senders_heap);
@@ -2349,10 +2294,14 @@ do_shutdown (void *cls)
     GNUNET_TRANSPORT_communicator_disconnect (ch);
     ch = NULL;
   }
+  if (NULL != ah)
+  {
+    GNUNET_TRANSPORT_application_done (ah);
+    ah = NULL;
+  }
   if (NULL != stats)
   {
-    GNUNET_STATISTICS_destroy (stats,
-                              GNUNET_NO);
+    GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
     stats = NULL;
   }
   if (NULL != my_private_key)
@@ -2362,8 +2311,8 @@ do_shutdown (void *cls)
   }
   if (NULL != is)
   {
-     GNUNET_NT_scanner_done (is);
-     is = NULL;
+    GNUNET_NT_scanner_done (is);
+    is = NULL;
   }
 }
 
@@ -2383,19 +2332,19 @@ enc_notify_cb (void *cls,
                const struct GNUNET_MessageHeader *msg)
 {
   const struct UDPAck *ack;
-  
+
   (void) cls;
-  if ( (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_ACK) ||
-       (ntohs (msg->size) != sizeof (struct UDPAck)) )
+  if ((ntohs (msg->type) != GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_ACK) ||
+      (ntohs (msg->size) != sizeof (struct UDPAck)))
   {
     GNUNET_break_op (0);
     return;
   }
   ack = (const struct UDPAck *) msg;
   GNUNET_CONTAINER_multipeermap_get_multiple (receivers,
-                                             sender,
-                                             &handle_ack,
-                                             (void *) ack);
+                                              sender,
+                                              &handle_ack,
+                                              (void *) ack);
 }
 
 
@@ -2406,7 +2355,7 @@ enc_notify_cb (void *cls,
  * @param cls closure
  * @param app_ctx[in,out] location where the app can store stuff
  *                  on add and retrieve it on remove
- * @param add_remove #GNUNET_YES to add a new public IP address, 
+ * @param add_remove #GNUNET_YES to add a new public IP address,
  *                   #GNUNET_NO to remove a previous (now invalid) one
  * @param ac address class the address belongs to
  * @param addr either the previous or the new public IP address
@@ -2414,11 +2363,11 @@ enc_notify_cb (void *cls,
  */
 static void
 nat_address_cb (void *cls,
-               void **app_ctx,
-               int add_remove,
-               enum GNUNET_NAT_AddressClass ac,
-               const struct sockaddr *addr,
-               socklen_t addrlen)
+                void **app_ctx,
+                int add_remove,
+                enum GNUNET_NAT_AddressClass ac,
+                const struct sockaddr *addr,
+                socklen_t addrlen)
 {
   char *my_addr;
   struct GNUNET_TRANSPORT_AddressIdentifier *ai;
@@ -2428,17 +2377,15 @@ nat_address_cb (void *cls,
     enum GNUNET_NetworkType nt;
 
     GNUNET_asprintf (&my_addr,
-                    "%s-%s",
-                    COMMUNICATOR_ADDRESS_PREFIX,
-                    GNUNET_a2s (addr,
-                                addrlen));
-    nt = GNUNET_NT_scanner_get_type (is,
-                                    addr,
-                                    addrlen); 
-    ai = GNUNET_TRANSPORT_communicator_address_add (ch,
-                                                   my_addr,
-                                                   nt,
-                                                   GNUNET_TIME_UNIT_FOREVER_REL);
+                     "%s-%s",
+                     COMMUNICATOR_ADDRESS_PREFIX,
+                     GNUNET_a2s (addr, addrlen));
+    nt = GNUNET_NT_scanner_get_type (is, addr, addrlen);
+    ai =
+      GNUNET_TRANSPORT_communicator_address_add (ch,
+                                                 my_addr,
+                                                 nt,
+                                                 GNUNET_TIME_UNIT_FOREVER_REL);
     GNUNET_free (my_addr);
     *app_ctx = ai;
   }
@@ -2463,67 +2410,57 @@ ifc_broadcast (void *cls)
   struct GNUNET_TIME_Relative delay;
 
   delay = BROADCAST_FREQUENCY;
-  delay.rel_value_us = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
-                                                delay.rel_value_us);
-  bi->broadcast_task
-    = GNUNET_SCHEDULER_add_delayed (INTERFACE_SCAN_FREQUENCY,
-                                   &ifc_broadcast,
-                                   bi);
-  
-  switch (bi->sa->sa_family) {
-  case AF_INET:
-    {
-      static int yes = 1;
-      static int no = 0;
-      ssize_t sent;
-    
-      if (GNUNET_OK !=
-         GNUNET_NETWORK_socket_setsockopt (udp_sock,
-                                           SOL_SOCKET,
-                                           SO_BROADCAST,
-                                           &yes,
-                                           sizeof (int)))
-       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
-                            "setsockopt");
-      sent = GNUNET_NETWORK_socket_sendto (udp_sock,
-                                          &bi->bcm,
-                                          sizeof (bi->bcm),
-                                          bi->ba,
-                                          bi->salen);
-      if (-1 == sent)
-       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
-                            "sendto");
-      if (GNUNET_OK !=
-         GNUNET_NETWORK_socket_setsockopt (udp_sock,
-                                           SOL_SOCKET,
-                                           SO_BROADCAST,
-                                           &no,
-                                           sizeof (int)))
-       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
-                            "setsockopt");
-      break;
-    }
-  case AF_INET6:
-    {
-      ssize_t sent;
-      struct sockaddr_in6 dst;
-
-      dst.sin6_family = AF_INET6;
-      dst.sin6_port = htons (my_port);
-      dst.sin6_addr = bi->mcreq.ipv6mr_multiaddr;
-      dst.sin6_scope_id = ((struct sockaddr_in6*) bi->ba)->sin6_scope_id;
-
-      sent = GNUNET_NETWORK_socket_sendto (udp_sock,
-                                          &bi->bcm,
-                                          sizeof (bi->bcm),
-                                          (const struct sockaddr *)
-                                          &dst,
-                                          sizeof (dst));
-      if (-1 == sent)
-       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
-                            "sendto");
-      break;
-    }
+  delay.rel_value_us =
+    GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, delay.rel_value_us);
+  bi->broadcast_task =
+    GNUNET_SCHEDULER_add_delayed (INTERFACE_SCAN_FREQUENCY, &ifc_broadcast, bi);
+
+  switch (bi->sa->sa_family)
+  {
+  case AF_INET: {
+    static int yes = 1;
+    static int no = 0;
+    ssize_t sent;
+
+    if (GNUNET_OK != GNUNET_NETWORK_socket_setsockopt (udp_sock,
+                                                       SOL_SOCKET,
+                                                       SO_BROADCAST,
+                                                       &yes,
+                                                       sizeof (int)))
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
+    sent = GNUNET_NETWORK_socket_sendto (udp_sock,
+                                         &bi->bcm,
+                                         sizeof (bi->bcm),
+                                         bi->ba,
+                                         bi->salen);
+    if (-1 == sent)
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "sendto");
+    if (GNUNET_OK != GNUNET_NETWORK_socket_setsockopt (udp_sock,
+                                                       SOL_SOCKET,
+                                                       SO_BROADCAST,
+                                                       &no,
+                                                       sizeof (int)))
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
+    break;
+  }
+  case AF_INET6: {
+    ssize_t sent;
+    struct sockaddr_in6 dst;
+
+    dst.sin6_family = AF_INET6;
+    dst.sin6_port = htons (my_port);
+    dst.sin6_addr = bi->mcreq.ipv6mr_multiaddr;
+    dst.sin6_scope_id = ((struct sockaddr_in6 *) bi->ba)->sin6_scope_id;
+
+    sent = GNUNET_NETWORK_socket_sendto (udp_sock,
+                                         &bi->bcm,
+                                         sizeof (bi->bcm),
+                                         (const struct sockaddr *) &dst,
+                                         sizeof (dst));
+    if (-1 == sent)
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "sendto");
+    break;
+  }
   default:
     GNUNET_break (0);
     break;
@@ -2539,7 +2476,8 @@ ifc_broadcast (void *cls)
  * @param name name of the interface (can be NULL for unknown)
  * @param isDefault is this presumably the default interface
  * @param addr address of this interface (can be NULL for unknown or unassigned)
- * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned)
+ * @param broadcast_addr the broadcast address (can be NULL for unknown or
+ * unassigned)
  * @param netmask the network mask (can be NULL for unknown or unassigned)
  * @param addrlen length of the address
  * @return #GNUNET_OK to continue iteration, #GNUNET_SYSERR to abort
@@ -2550,7 +2488,8 @@ iface_proc (void *cls,
             int isDefault,
             const struct sockaddr *addr,
             const struct sockaddr *broadcast_addr,
-            const struct sockaddr *netmask, socklen_t addrlen)
+            const struct sockaddr *netmask,
+            socklen_t addrlen)
 {
   struct BroadcastInterface *bi;
   enum GNUNET_NetworkType network;
@@ -2558,9 +2497,7 @@ iface_proc (void *cls,
 
   (void) cls;
   (void) netmask;
-  network = GNUNET_NT_scanner_get_type (is,
-                                       addr,
-                                       addrlen);
+  network = GNUNET_NT_scanner_get_type (is, addr, addrlen);
   if (GNUNET_NT_LOOPBACK == network)
   {
     /* Broadcasting on loopback does not make sense */
@@ -2570,59 +2507,43 @@ iface_proc (void *cls,
     return GNUNET_YES; /* need to know our address! */
   for (bi = bi_head; NULL != bi; bi = bi->next)
   {
-    if ( (bi->salen == addrlen) &&
-        (0 == memcmp (addr,
-                      bi->sa,
-                      addrlen)) )
+    if ((bi->salen == addrlen) && (0 == memcmp (addr, bi->sa, addrlen)))
     {
       bi->found = GNUNET_YES;
       return GNUNET_OK;
     }
   }
 
-  if ( (AF_INET6 == addr->sa_family) &&
-       (NULL == broadcast_addr) )
+  if ((AF_INET6 == addr->sa_family) && (NULL == broadcast_addr))
     return GNUNET_OK; /* broadcast_addr is required for IPv6! */
-  if ( (AF_INET6 == addr->sa_family) &&
-       (GNUNET_YES != have_v6_socket) )
+  if ((AF_INET6 == addr->sa_family) && (GNUNET_YES != have_v6_socket))
     return GNUNET_OK; /* not using IPv6 */
-  
+
   bi = GNUNET_new (struct BroadcastInterface);
-  bi->sa = GNUNET_memdup (addr,
-                         addrlen);
+  bi->sa = GNUNET_memdup (addr, addrlen);
   if (NULL != broadcast_addr)
-    bi->ba = GNUNET_memdup (broadcast_addr,
-                           addrlen);
+    bi->ba = GNUNET_memdup (broadcast_addr, addrlen);
   bi->salen = addrlen;
   bi->found = GNUNET_YES;
   bi->bcm.sender = my_identity;
   ubs.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_UDP_BROADCAST);
   ubs.purpose.size = htonl (sizeof (ubs));
   ubs.sender = my_identity;
-  GNUNET_CRYPTO_hash (addr,
-                     addrlen,
-                     &ubs.h_address);
-  GNUNET_assert (GNUNET_OK ==
-                GNUNET_CRYPTO_eddsa_sign (my_private_key,
-                                          &ubs.purpose,
-                                          &bi->bcm.sender_sig));
-  bi->broadcast_task = GNUNET_SCHEDULER_add_now (&ifc_broadcast,
-                                                bi);
-  GNUNET_CONTAINER_DLL_insert (bi_head,
-                              bi_tail,
-                              bi);
-  if ( (AF_INET6 == addr->sa_family) &&
-       (NULL != broadcast_addr) )
+  GNUNET_CRYPTO_hash (addr, addrlen, &ubs.h_address);
+  GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (my_private_key,
+                                                        &ubs.purpose,
+                                                        &bi->bcm.sender_sig));
+  bi->broadcast_task = GNUNET_SCHEDULER_add_now (&ifc_broadcast, bi);
+  GNUNET_CONTAINER_DLL_insert (bi_head, bi_tail, bi);
+  if ((AF_INET6 == addr->sa_family) && (NULL != broadcast_addr))
   {
     /* Create IPv6 multicast request */
-    const struct sockaddr_in6 *s6
-      = (const struct sockaddr_in6 *) broadcast_addr;
-
-    GNUNET_assert (1 ==
-                   inet_pton (AF_INET6,
-                             "FF05::13B",
-                              &bi->mcreq.ipv6mr_multiaddr));
-    
+    const struct sockaddr_in6 *s6 =
+      (const struct sockaddr_in6 *) broadcast_addr;
+
+    GNUNET_assert (
+      1 == inet_pton (AF_INET6, "FF05::13B", &bi->mcreq.ipv6mr_multiaddr));
+
     /* http://tools.ietf.org/html/rfc2553#section-5.2:
      *
      * IPV6_JOIN_GROUP
@@ -2637,16 +2558,13 @@ iface_proc (void *cls,
     bi->mcreq.ipv6mr_interface = s6->sin6_scope_id;
 
     /* Join the multicast group */
-    if (GNUNET_OK !=
-        GNUNET_NETWORK_socket_setsockopt
-        (udp_sock,
-        IPPROTO_IPV6,
-        IPV6_JOIN_GROUP,
-         &bi->mcreq,
-        sizeof (bi->mcreq)))
+    if (GNUNET_OK != GNUNET_NETWORK_socket_setsockopt (udp_sock,
+                                                       IPPROTO_IPV6,
+                                                       IPV6_JOIN_GROUP,
+                                                       &bi->mcreq,
+                                                       sizeof (bi->mcreq)))
     {
-      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
-                          "setsockopt");
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
     }
   }
   return GNUNET_OK;
@@ -2662,26 +2580,20 @@ static void
 do_broadcast (void *cls)
 {
   struct BroadcastInterface *bin;
-  
+
   (void) cls;
-  for (struct BroadcastInterface *bi = bi_head;
-       NULL != bi;
-       bi = bi->next)
+  for (struct BroadcastInterface *bi = bi_head; NULL != bi; bi = bi->next)
     bi->found = GNUNET_NO;
-  GNUNET_OS_network_interfaces_list (&iface_proc,
-                                    NULL);
-  for (struct BroadcastInterface *bi = bi_head;
-       NULL != bi;
-       bi = bin)
+  GNUNET_OS_network_interfaces_list (&iface_proc, NULL);
+  for (struct BroadcastInterface *bi = bi_head; NULL != bi; bi = bin)
   {
     bin = bi->next;
     if (GNUNET_NO == bi->found)
       bi_destroy (bi);
   }
-  broadcast_task
-    = GNUNET_SCHEDULER_add_delayed (INTERFACE_SCAN_FREQUENCY,
-                                   &do_broadcast,
-                                   NULL);
+  broadcast_task = GNUNET_SCHEDULER_add_delayed (INTERFACE_SCAN_FREQUENCY,
+                                                 &do_broadcast,
+                                                 NULL);
 }
 
 
@@ -2704,14 +2616,14 @@ run (void *cls,
   socklen_t in_len;
   struct sockaddr_storage in_sto;
   socklen_t sto_len;
-  
+
   (void) cls;
   cfg = c;
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_filename (cfg,
-                                              COMMUNICATOR_CONFIG_SECTION,
-                                              "BINDTO",
-                                              &bindto))
+                                               COMMUNICATOR_CONFIG_SECTION,
+                                               "BINDTO",
+                                               &bindto))
   {
     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
                                COMMUNICATOR_CONFIG_SECTION,
@@ -2719,37 +2631,29 @@ run (void *cls,
     return;
   }
 
-  in = udp_address_to_sockaddr (bindto,
-                               &in_len);
+  in = udp_address_to_sockaddr (bindto, &in_len);
   if (NULL == in)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               "Failed to setup UDP socket address with path `%s'\n",
-               bindto);
+                "Failed to setup UDP socket address with path `%s'\n",
+                bindto);
     GNUNET_free (bindto);
     return;
   }
-  udp_sock = GNUNET_NETWORK_socket_create (in->sa_family,
-                                          SOCK_DGRAM,
-                                          IPPROTO_UDP);
+  udp_sock =
+    GNUNET_NETWORK_socket_create (in->sa_family, SOCK_DGRAM, IPPROTO_UDP);
   if (NULL == udp_sock)
   {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
-                        "socket");
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
     GNUNET_free (in);
     GNUNET_free (bindto);
     return;
   }
   if (AF_INET6 == in->sa_family)
     have_v6_socket = GNUNET_YES;
-  if (GNUNET_OK !=
-      GNUNET_NETWORK_socket_bind (udp_sock,
-                                  in,
-                                 in_len))
+  if (GNUNET_OK != GNUNET_NETWORK_socket_bind (udp_sock, in, in_len))
   {
-    GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
-                             "bind",
-                             bindto);
+    GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "bind", bindto);
     GNUNET_NETWORK_socket_close (udp_sock);
     udp_sock = NULL;
     GNUNET_free (in);
@@ -2760,12 +2664,10 @@ run (void *cls,
      thus, get the real IN-address from the socket */
   sto_len = sizeof (in_sto);
   if (0 != getsockname (GNUNET_NETWORK_get_fd (udp_sock),
-                       (struct sockaddr *) &in_sto,
-                       &sto_len))
+                        (struct sockaddr *) &in_sto,
+                        &sto_len))
   {
-    memcpy (&in_sto,
-           in,
-           in_len);
+    memcpy (&in_sto, in, in_len);
     sto_len = in_len;
   }
   GNUNET_free (in);
@@ -2773,9 +2675,8 @@ run (void *cls,
   in = (struct sockaddr *) &in_sto;
   in_len = sto_len;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Bound to `%s'\n",
-             GNUNET_a2s ((const struct sockaddr *) &in_sto,
-                         sto_len));
+              "Bound to `%s'\n",
+              GNUNET_a2s ((const struct sockaddr *) &in_sto, sto_len));
   switch (in->sa_family)
   {
   case AF_INET:
@@ -2788,40 +2689,37 @@ run (void *cls,
     GNUNET_break (0);
     my_port = 0;
   }
-  stats = GNUNET_STATISTICS_create ("C-UDP",
-                                   cfg);
-  senders = GNUNET_CONTAINER_multipeermap_create (32,
-                                                 GNUNET_YES);
-  receivers = GNUNET_CONTAINER_multipeermap_create (32,
-                                                   GNUNET_YES);
+  stats = GNUNET_STATISTICS_create ("C-UDP", cfg);
+  senders = GNUNET_CONTAINER_multipeermap_create (32, GNUNET_YES);
+  receivers = GNUNET_CONTAINER_multipeermap_create (32, GNUNET_YES);
   senders_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
-  receivers_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
-  key_cache = GNUNET_CONTAINER_multishortmap_create (1024,
-                                                    GNUNET_YES);
-  GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
-                                NULL);
+  receivers_heap =
+    GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
+  key_cache = GNUNET_CONTAINER_multishortmap_create (1024, GNUNET_YES);
+  GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
   is = GNUNET_NT_scanner_init ();
   my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
   if (NULL == my_private_key)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _("Transport service is lacking key configuration settings. Exiting.\n"));
+    GNUNET_log (
+      GNUNET_ERROR_TYPE_ERROR,
+      _ (
+        "Transport service is lacking key configuration settings. Exiting.\n"));
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
-  GNUNET_CRYPTO_eddsa_key_get_public (my_private_key,
-                                      &my_identity.public_key);
+  GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, &my_identity.public_key);
   /* start reading */
   read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
-                                            udp_sock,
-                                            &sock_read,
-                                            NULL);
+                                             udp_sock,
+                                             &sock_read,
+                                             NULL);
   ch = GNUNET_TRANSPORT_communicator_connect (cfg,
-                                             COMMUNICATOR_CONFIG_SECTION,
-                                             COMMUNICATOR_ADDRESS_PREFIX,
+                                              COMMUNICATOR_CONFIG_SECTION,
+                                              COMMUNICATOR_ADDRESS_PREFIX,
                                               GNUNET_TRANSPORT_CC_UNRELIABLE,
-                                             &mq_init,
-                                             NULL,
+                                              &mq_init,
+                                              NULL,
                                               &enc_notify_cb,
                                               NULL);
   if (NULL == ch)
@@ -2830,24 +2728,30 @@ run (void *cls,
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
+  ah = GNUNET_TRANSPORT_application_init (cfg);
+  if (NULL == ah)
+  {
+    GNUNET_break (0);
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
   /* start broadcasting */
   if (GNUNET_YES !=
       GNUNET_CONFIGURATION_get_value_yesno (cfg,
-                                           COMMUNICATOR_CONFIG_SECTION,
-                                           "DISABLE_BROADCAST"))
+                                            COMMUNICATOR_CONFIG_SECTION,
+                                            "DISABLE_BROADCAST"))
   {
-    broadcast_task = GNUNET_SCHEDULER_add_now (&do_broadcast,
-                                              NULL);
-  }  
+    broadcast_task = GNUNET_SCHEDULER_add_now (&do_broadcast, NULL);
+  }
   nat = GNUNET_NAT_register (cfg,
-                            COMMUNICATOR_CONFIG_SECTION,
-                            IPPROTO_UDP,
-                            1 /* one address */,
-                            (const struct sockaddr **) &in,
-                            &in_len,
-                            &nat_address_cb,
-                            NULL /* FIXME: support reversal: #5529 */,
-                            NULL /* closure */);
+                             COMMUNICATOR_CONFIG_SECTION,
+                             IPPROTO_UDP,
+                             1 /* one address */,
+                             (const struct sockaddr **) &in,
+                             &in_len,
+                             &nat_address_cb,
+                             NULL /* FIXME: support reversal: #5529 */,
+                             NULL /* closure */);
 }
 
 
@@ -2859,28 +2763,25 @@ run (void *cls,
  * @return 0 ok, 1 on error
  */
 int
-main (int argc,
-      char *const *argv)
+main (int argc, char *const *argv)
 {
   static const struct GNUNET_GETOPT_CommandLineOption options[] = {
-    GNUNET_GETOPT_OPTION_END
-  };
+    GNUNET_GETOPT_OPTION_END};
   int ret;
 
-  if (GNUNET_OK !=
-      GNUNET_STRINGS_get_utf8_args (argc, argv,
-                                   &argc, &argv))
+  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
     return 2;
 
-  ret =
-      (GNUNET_OK ==
-       GNUNET_PROGRAM_run (argc, argv,
-                           "gnunet-communicator-udp",
-                           _("GNUnet UDP communicator"),
-                           options,
-                          &run,
-                          NULL)) ? 0 : 1;
-  GNUNET_free ((void*) argv);
+  ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc,
+                                          argv,
+                                          "gnunet-communicator-udp",
+                                          _ ("GNUnet UDP communicator"),
+                                          options,
+                                          &run,
+                                          NULL))
+          ? 0
+          : 1;
+  GNUNET_free ((void *) argv);
   return ret;
 }