+GNUNET_HashCode *
+address4_mapping_exists (uint32_t addr)
+{
+ GNUNET_HashCode *key = GNUNET_malloc (sizeof (GNUNET_HashCode));
+
+ memset (key, 0, sizeof (GNUNET_HashCode));
+ unsigned char *c = (unsigned char *) &addr;
+ unsigned char *k = (unsigned char *) key;
+ unsigned int i;
+
+ for (i = 0; i < 4; i++)
+ k[3 - i] = c[i];
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "a4_m_e: getting with key %08x, addr is %08x, %d.%d.%d.%d\n",
+ *((uint32_t *) (key)), addr, c[0], c[1], c[2], c[3]);
+
+ if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (hashmap, key))
+ return key;
+ else
+ {
+ GNUNET_free (key);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mapping not found!\n");
+ return NULL;
+ }
+}
+
+static void
+collect_mappings (void *cls
+ __attribute__ ((unused)),
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
+ return;
+
+ struct map_entry *me = GNUNET_CONTAINER_heap_remove_root (heap);
+
+ /* This is free()ed memory! */
+ me->heap_node = NULL;
+
+ /* FIXME! GNUNET_MESH_close_tunnel(me->tunnel); */
+
+ GNUNET_assert (GNUNET_YES ==
+ GNUNET_CONTAINER_multihashmap_remove (hashmap, &me->hash, me));
+
+ GNUNET_free (me);
+}
+
+void
+send_icmp4_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
+ return;
+
+ struct ip_icmp *request = cls;
+
+ struct ip_icmp *response = alloca (ntohs (request->shdr.size));
+
+ GNUNET_assert (response != NULL);
+ memset (response, 0, ntohs (request->shdr.size));
+
+ response->shdr.size = request->shdr.size;
+ response->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
+
+ response->tun.flags = 0;
+ response->tun.type = htons (0x0800);
+
+ response->ip_hdr.hdr_lngth = 5;
+ response->ip_hdr.version = 4;
+ response->ip_hdr.proto = 0x01;
+ response->ip_hdr.dadr = request->ip_hdr.sadr;
+ response->ip_hdr.sadr = request->ip_hdr.dadr;
+ response->ip_hdr.tot_lngth = request->ip_hdr.tot_lngth;
+
+ response->ip_hdr.chks =
+ calculate_ip_checksum ((uint16_t *) & response->ip_hdr, 20);
+
+ response->icmp_hdr.code = 0;
+ response->icmp_hdr.type = 0x0;
+
+ /* Magic, more Magic! */
+ response->icmp_hdr.chks = request->icmp_hdr.chks + 0x8;
+
+ /* Copy the rest of the packet */
+ memcpy (response + 1, request + 1,
+ ntohs (request->shdr.size) - sizeof (struct ip_icmp));
+
+ write_to_helper (response, ntohs (response->shdr.size));
+
+ GNUNET_free (request);
+}
+
+void
+send_icmp6_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
+ return;
+
+ struct ip6_icmp *request = cls;
+
+ struct ip6_icmp *response = alloca (ntohs (request->shdr.size));
+
+ GNUNET_assert (response != NULL);
+ memset (response, 0, ntohs (request->shdr.size));
+
+ response->shdr.size = request->shdr.size;
+ response->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
+
+ response->tun.flags = 0;
+ response->tun.type = htons (0x86dd);
+
+ response->ip6_hdr.hoplmt = 255;
+ response->ip6_hdr.paylgth = request->ip6_hdr.paylgth;
+ response->ip6_hdr.nxthdr = 0x3a;
+ response->ip6_hdr.version = 6;
+ memcpy (&response->ip6_hdr.sadr, &request->ip6_hdr.dadr, 16);
+ memcpy (&response->ip6_hdr.dadr, &request->ip6_hdr.sadr, 16);
+
+ response->icmp_hdr.code = 0;
+ response->icmp_hdr.type = 0x81;
+
+ /* Magic, more Magic! */
+ response->icmp_hdr.chks = request->icmp_hdr.chks - 0x1;
+
+ /* Copy the rest of the packet */
+ memcpy (response + 1, request + 1,
+ ntohs (request->shdr.size) - sizeof (struct ip6_icmp));
+
+ write_to_helper (response, ntohs (response->shdr.size));
+
+ GNUNET_free (request);
+}