aboutsummaryrefslogtreecommitdiff
path: root/src/vpn
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-09-22 15:25:57 +0000
committerChristian Grothoff <christian@grothoff.org>2013-09-22 15:25:57 +0000
commit69cf9d7768b72fd21a9aa2ba9e208dba193a21a1 (patch)
treefede2ce61fcda3bc6dd78ec1204ec3931e2feba0 /src/vpn
parent2e1bfb2f75c216e0dbacb31a9e58e01bd1dff6d4 (diff)
downloadgnunet-69cf9d7768b72fd21a9aa2ba9e208dba193a21a1.tar.gz
gnunet-69cf9d7768b72fd21a9aa2ba9e208dba193a21a1.zip
fixing #2916, but untested
Diffstat (limited to 'src/vpn')
-rw-r--r--src/vpn/gnunet-service-vpn.c219
1 files changed, 153 insertions, 66 deletions
diff --git a/src/vpn/gnunet-service-vpn.c b/src/vpn/gnunet-service-vpn.c
index f26369d11..13cbf5021 100644
--- a/src/vpn/gnunet-service-vpn.c
+++ b/src/vpn/gnunet-service-vpn.c
@@ -28,7 +28,7 @@
28 * 28 *
29 * TODO: 29 * TODO:
30 * - keep multiple peers/mesh tunnels ready as alternative exits / 30 * - keep multiple peers/mesh tunnels ready as alternative exits /
31 * recover from tunnel-to-exit failure gracefully 31 * detect & recover from tunnel-to-exit failure gracefully
32 */ 32 */
33#include "platform.h" 33#include "platform.h"
34#include "gnunet_util_lib.h" 34#include "gnunet_util_lib.h"
@@ -50,13 +50,51 @@
50#define MAX_MESSAGE_QUEUE_SIZE 4 50#define MAX_MESSAGE_QUEUE_SIZE 4
51 51
52 52
53#define PORT_VPN 42
54
55/** 53/**
56 * State we keep for each of our tunnels. 54 * State we keep for each of our tunnels.
57 */ 55 */
58struct TunnelState; 56struct TunnelState;
59 57
58/**
59 * Information we track for each IP address to determine which tunnel
60 * to send the traffic over to the destination.
61 */
62struct DestinationEntry;
63
64/**
65 * List of tunnels we keep for each destination port for a given
66 * destination entry.
67 */
68struct DestinationTunnel
69{
70
71 /**
72 * Kept in a DLL.
73 */
74 struct DestinationTunnel *next;
75
76 /**
77 * Kept in a DLL.
78 */
79 struct DestinationTunnel *prev;
80
81 /**
82 * Destination entry list this `struct DestinationTunnel` belongs with.
83 */
84 struct DestinationEntry *destination;
85
86 /**
87 * Pre-allocated tunnel for this destination, or NULL for none.
88 */
89 struct TunnelState *ts;
90
91 /**
92 * Destination port this tunnel state is used for.
93 */
94 uint16_t destination_port;
95
96};
97
60 98
61/** 99/**
62 * Information we track for each IP address to determine which tunnel 100 * Information we track for each IP address to determine which tunnel
@@ -72,9 +110,14 @@ struct DestinationEntry
72 struct GNUNET_HashCode key; 110 struct GNUNET_HashCode key;
73 111
74 /** 112 /**
75 * Pre-allocated tunnel for this destination, or NULL for none. 113 * Head of DLL of tunnels associated with this destination.
76 */ 114 */
77 struct TunnelState *ts; 115 struct DestinationTunnel *dt_head;
116
117 /**
118 * Tail of DLL of tunnels associated with this destination.
119 */
120 struct DestinationTunnel *dt_tail;
78 121
79 /** 122 /**
80 * Entry for this entry in the destination_heap. 123 * Entry for this entry in the destination_heap.
@@ -207,7 +250,7 @@ struct TunnelState
207 * Destination entry that has a pointer to this tunnel state; 250 * Destination entry that has a pointer to this tunnel state;
208 * NULL if this tunnel state is in the tunnel map. 251 * NULL if this tunnel state is in the tunnel map.
209 */ 252 */
210 struct DestinationEntry *destination_container; 253 struct DestinationTunnel *destination_container;
211 254
212 /** 255 /**
213 * Destination to which this tunnel leads. Note that 256 * Destination to which this tunnel leads. Note that
@@ -655,9 +698,9 @@ send_to_tunnel (struct TunnelMessageQueueEntry *tnq,
655 * @param cls the 'struct TunnelState' 698 * @param cls the 'struct TunnelState'
656 * @param id Peer providing a regex that matches the string. 699 * @param id Peer providing a regex that matches the string.
657 * @param get_path Path of the get request. 700 * @param get_path Path of the get request.
658 * @param get_path_length Lenght of get_path. 701 * @param get_path_length Lenght of @a get_path.
659 * @param put_path Path of the put request. 702 * @param put_path Path of the put request.
660 * @param put_path_length Length of the put_path. 703 * @param put_path_length Length of the @a put_path.
661 */ 704 */
662static void 705static void
663handle_regex_result (void *cls, 706handle_regex_result (void *cls,
@@ -668,13 +711,26 @@ handle_regex_result (void *cls,
668 unsigned int put_path_length) 711 unsigned int put_path_length)
669{ 712{
670 struct TunnelState *ts = cls; 713 struct TunnelState *ts = cls;
714 unsigned int apptype;
671 715
672 GNUNET_REGEX_search_cancel (ts->search); 716 GNUNET_REGEX_search_cancel (ts->search);
673 ts->search = NULL; 717 ts->search = NULL;
718 switch (ts->af)
719 {
720 case AF_INET:
721 apptype = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY;
722 break;
723 case AF_INET6:
724 apptype = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY;
725 break;
726 default:
727 GNUNET_break (0);
728 return;
729 }
674 ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle, 730 ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
675 ts, 731 ts,
676 id, 732 id,
677 PORT_VPN, 733 apptype,
678 GNUNET_YES, 734 GNUNET_YES,
679 GNUNET_NO); 735 GNUNET_NO);
680} 736}
@@ -683,32 +739,45 @@ handle_regex_result (void *cls,
683/** 739/**
684 * Initialize the given destination entry's mesh tunnel. 740 * Initialize the given destination entry's mesh tunnel.
685 * 741 *
686 * @param de destination entry for which we need to setup a tunnel 742 * @param dt destination tunnel for which we need to setup a tunnel
687 * @param client_af address family of the address returned to the client 743 * @param client_af address family of the address returned to the client
688 * @return tunnel state of the tunnel that was created 744 * @return tunnel state of the tunnel that was created
689 */ 745 */
690static struct TunnelState * 746static struct TunnelState *
691create_tunnel_to_destination (struct DestinationEntry *de, 747create_tunnel_to_destination (struct DestinationTunnel *dt,
692 int client_af) 748 int client_af)
693{ 749{
694 struct TunnelState *ts; 750 struct TunnelState *ts;
751 unsigned int apptype;
695 752
696 GNUNET_STATISTICS_update (stats, 753 GNUNET_STATISTICS_update (stats,
697 gettext_noop ("# Mesh tunnels created"), 754 gettext_noop ("# Mesh tunnels created"),
698 1, GNUNET_NO); 755 1, GNUNET_NO);
699 GNUNET_assert (NULL == de->ts); 756 GNUNET_assert (NULL == dt->ts);
757 switch (client_af)
758 {
759 case AF_INET:
760 apptype = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY;
761 break;
762 case AF_INET6:
763 apptype = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY;
764 break;
765 default:
766 GNUNET_break (0);
767 return NULL;
768 }
700 ts = GNUNET_new (struct TunnelState); 769 ts = GNUNET_new (struct TunnelState);
701 ts->af = client_af; 770 ts->af = client_af;
702 ts->destination = *de; 771 ts->destination = *dt->destination;
703 ts->destination.heap_node = NULL; /* copy is NOT in destination heap */ 772 ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
704 de->ts = ts; 773 dt->ts = ts;
705 ts->destination_container = de; /* we are referenced from de */ 774 ts->destination_container = dt; /* we are referenced from dt */
706 if (de->is_service) 775 if (dt->destination->is_service)
707 { 776 {
708 ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle, 777 ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
709 ts, 778 ts,
710 &de->details.service_destination.target, 779 &dt->destination->details.service_destination.target,
711 PORT_VPN, 780 apptype,
712 GNUNET_YES, 781 GNUNET_YES,
713 GNUNET_NO); 782 GNUNET_NO);
714 if (NULL == ts->tunnel) 783 if (NULL == ts->tunnel)
@@ -720,37 +789,40 @@ create_tunnel_to_destination (struct DestinationEntry *de,
720 } 789 }
721 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 790 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
722 "Creating tunnel to peer %s offering service %s\n", 791 "Creating tunnel to peer %s offering service %s\n",
723 GNUNET_i2s (&de->details.service_destination.target), 792 GNUNET_i2s (&dt->destination->details.service_destination.target),
724 GNUNET_h2s (&de->details.service_destination.service_descriptor)); 793 GNUNET_h2s (&dt->destination->details.service_destination.service_descriptor));
725 } 794 }
726 else 795 else
727 { 796 {
728 char *policy; 797 char *policy;
729 798
730 switch (de->details.exit_destination.af) 799 switch (dt->destination->details.exit_destination.af)
731 { 800 {
732 case AF_INET: 801 case AF_INET:
733 { 802 {
734 char address[GNUNET_TUN_IPV4_REGEXLEN]; 803 char address[GNUNET_TUN_IPV4_REGEXLEN];
735 804
736 GNUNET_TUN_ipv4toregexsearch (&de->details.exit_destination.ip.v4, 805 GNUNET_TUN_ipv4toregexsearch (&dt->destination->details.exit_destination.ip.v4,
737 "255.255.255.255", address); 806 "255.255.255.255",
738 GNUNET_asprintf (&policy, "%s%s%s", 807 address);
808 GNUNET_asprintf (&policy, "%s%s%s:%u",
739 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX, 809 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
740 "4", 810 "4",
741 address); 811 address,
812 (unsigned int) dt->destination_port);
742 break; 813 break;
743 } 814 }
744 case AF_INET6: 815 case AF_INET6:
745 { 816 {
746 char address[GNUNET_TUN_IPV6_REGEXLEN]; 817 char address[GNUNET_TUN_IPV6_REGEXLEN];
747 818
748 GNUNET_TUN_ipv6toregexsearch (&de->details.exit_destination.ip.v6, 819 GNUNET_TUN_ipv6toregexsearch (&dt->destination->details.exit_destination.ip.v6,
749 128, address); 820 128, address);
750 GNUNET_asprintf (&policy, "%s%s%s", 821 GNUNET_asprintf (&policy, "%s%s%s:%u",
751 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX, 822 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
752 "6", 823 "6",
753 address); 824 address,
825 (unsigned int) dt->destination_port);
754 break; 826 break;
755 } 827 }
756 default: 828 default:
@@ -798,7 +870,7 @@ expire_tunnel (struct TunnelState *except)
798 * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr) 870 * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
799 * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr) 871 * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
800 * @param payload payload of the packet after the IP header 872 * @param payload payload of the packet after the IP header
801 * @param payload_length number of bytes in payload 873 * @param payload_length number of bytes in @a payload
802 */ 874 */
803static void 875static void
804route_packet (struct DestinationEntry *destination, 876route_packet (struct DestinationEntry *destination,
@@ -818,6 +890,7 @@ route_packet (struct DestinationEntry *destination,
818 const struct GNUNET_TUN_UdpHeader *udp; 890 const struct GNUNET_TUN_UdpHeader *udp;
819 const struct GNUNET_TUN_TcpHeader *tcp; 891 const struct GNUNET_TUN_TcpHeader *tcp;
820 const struct GNUNET_TUN_IcmpHeader *icmp; 892 const struct GNUNET_TUN_IcmpHeader *icmp;
893 struct DestinationTunnel *dt;
821 uint16_t source_port; 894 uint16_t source_port;
822 uint16_t destination_port; 895 uint16_t destination_port;
823 896
@@ -943,6 +1016,9 @@ route_packet (struct DestinationEntry *destination,
943 xbuf, sizeof (xbuf)), 1016 xbuf, sizeof (xbuf)),
944 destination_port); 1017 destination_port);
945 } 1018 }
1019 for (dt = destination->dt_head; NULL != dt; dt = dt->next)
1020 if (dt->destination_port == destination_port)
1021 break;
946 } 1022 }
947 else 1023 else
948 { 1024 {
@@ -960,7 +1036,16 @@ route_packet (struct DestinationEntry *destination,
960 GNUNET_h2s (&destination->details.service_destination.service_descriptor), 1036 GNUNET_h2s (&destination->details.service_destination.service_descriptor),
961 GNUNET_i2s (&destination->details.service_destination.target)); 1037 GNUNET_i2s (&destination->details.service_destination.target));
962 } 1038 }
963 1039 dt = destination->dt_head;
1040 }
1041 if (NULL == dt)
1042 {
1043 dt = GNUNET_new (struct DestinationTunnel);
1044 dt->destination = destination;
1045 GNUNET_CONTAINER_DLL_insert (destination->dt_head,
1046 destination->dt_tail,
1047 dt);
1048 dt->destination_port = destination_port;
964 } 1049 }
965 1050
966 /* see if we have an existing tunnel for this destination */ 1051 /* see if we have an existing tunnel for this destination */
@@ -971,18 +1056,18 @@ route_packet (struct DestinationEntry *destination,
971 /* need to either use the existing tunnel from the destination (if still 1056 /* need to either use the existing tunnel from the destination (if still
972 available) or create a fresh one */ 1057 available) or create a fresh one */
973 is_new = GNUNET_YES; 1058 is_new = GNUNET_YES;
974 if (NULL == destination->ts) 1059 if (NULL == dt->ts)
975 ts = create_tunnel_to_destination (destination, af); 1060 ts = create_tunnel_to_destination (dt, af);
976 else 1061 else
977 ts = destination->ts; 1062 ts = dt->ts;
978 if (NULL == ts) 1063 if (NULL == ts)
979 return; 1064 return;
980 destination->ts = NULL; 1065 dt->ts = NULL;
981 ts->destination_container = NULL; /* no longer 'contained' */ 1066 ts->destination_container = NULL; /* no longer 'contained' */
982 /* now bind existing "unbound" tunnel to our IP/port tuple */ 1067 /* now bind existing "unbound" tunnel to our IP/port tuple */
983 ts->protocol = protocol; 1068 ts->protocol = protocol;
984 ts->af = af; 1069 ts->af = af;
985 if (af == AF_INET) 1070 if (AF_INET == af)
986 { 1071 {
987 ts->source_ip.v4 = * (const struct in_addr *) source_ip; 1072 ts->source_ip.v4 = * (const struct in_addr *) source_ip;
988 ts->destination_ip.v4 = * (const struct in_addr *) destination_ip; 1073 ts->destination_ip.v4 = * (const struct in_addr *) destination_ip;
@@ -1061,8 +1146,7 @@ route_packet (struct DestinationEntry *destination,
1061 GNUNET_break (0); 1146 GNUNET_break (0);
1062 return; 1147 return;
1063 } 1148 }
1064 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + 1149 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1065 mlen);
1066 tnq->len = mlen; 1150 tnq->len = mlen;
1067 tnq->msg = &tnq[1]; 1151 tnq->msg = &tnq[1];
1068 uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1]; 1152 uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1];
@@ -1279,8 +1363,7 @@ route_packet (struct DestinationEntry *destination,
1279 GNUNET_break (0); 1363 GNUNET_break (0);
1280 return; 1364 return;
1281 } 1365 }
1282 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + 1366 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1283 mlen);
1284 tnq->msg = &tnq[1]; 1367 tnq->msg = &tnq[1];
1285 iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1]; 1368 iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1];
1286 iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET); 1369 iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
@@ -1440,7 +1523,8 @@ route_packet (struct DestinationEntry *destination,
1440 * @param message message we got from the client (VPN tunnel interface) 1523 * @param message message we got from the client (VPN tunnel interface)
1441 */ 1524 */
1442static int 1525static int
1443message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED, 1526message_token (void *cls,
1527 void *client,
1444 const struct GNUNET_MessageHeader *message) 1528 const struct GNUNET_MessageHeader *message)
1445{ 1529{
1446 const struct GNUNET_TUN_Layer2PacketHeader *tun; 1530 const struct GNUNET_TUN_Layer2PacketHeader *tun;
@@ -1614,7 +1698,8 @@ make_up_icmpv6_payload (struct TunnelState *ts,
1614 * #GNUNET_SYSERR to close it (signal serious error) 1698 * #GNUNET_SYSERR to close it (signal serious error)
1615 */ 1699 */
1616static int 1700static int
1617receive_icmp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, 1701receive_icmp_back (void *cls,
1702 struct GNUNET_MESH_Tunnel *tunnel,
1618 void **tunnel_ctx, 1703 void **tunnel_ctx,
1619 const struct GNUNET_MessageHeader *message) 1704 const struct GNUNET_MessageHeader *message)
1620{ 1705{
@@ -1952,7 +2037,8 @@ receive_icmp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1952 * #GNUNET_SYSERR to close it (signal serious error) 2037 * #GNUNET_SYSERR to close it (signal serious error)
1953 */ 2038 */
1954static int 2039static int
1955receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, 2040receive_udp_back (void *cls,
2041 struct GNUNET_MESH_Tunnel *tunnel,
1956 void **tunnel_ctx, 2042 void **tunnel_ctx,
1957 const struct GNUNET_MessageHeader *message) 2043 const struct GNUNET_MessageHeader *message)
1958{ 2044{
@@ -2106,7 +2192,8 @@ receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2106 * #GNUNET_SYSERR to close it (signal serious error) 2192 * #GNUNET_SYSERR to close it (signal serious error)
2107 */ 2193 */
2108static int 2194static int
2109receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, 2195receive_tcp_back (void *cls,
2196 struct GNUNET_MESH_Tunnel *tunnel,
2110 void **tunnel_ctx, 2197 void **tunnel_ctx,
2111 const struct GNUNET_MessageHeader *message) 2198 const struct GNUNET_MessageHeader *message)
2112{ 2199{
@@ -2357,15 +2444,24 @@ allocate_v6_address (struct in6_addr *v6)
2357static void 2444static void
2358free_destination_entry (struct DestinationEntry *de) 2445free_destination_entry (struct DestinationEntry *de)
2359{ 2446{
2447 struct DestinationTunnel *dt;
2448
2360 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2449 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2361 "Cleaning up destination entry\n"); 2450 "Cleaning up destination entry\n");
2362 GNUNET_STATISTICS_update (stats, 2451 GNUNET_STATISTICS_update (stats,
2363 gettext_noop ("# Active destinations"), 2452 gettext_noop ("# Active destinations"),
2364 -1, GNUNET_NO); 2453 -1, GNUNET_NO);
2365 if (NULL != de->ts) 2454 while (NULL != (dt = de->dt_head))
2366 { 2455 {
2367 free_tunnel_state (de->ts); 2456 if (NULL != dt->ts)
2368 GNUNET_assert (NULL == de->ts); 2457 {
2458 free_tunnel_state (dt->ts);
2459 GNUNET_assert (NULL == dt->ts);
2460 }
2461 GNUNET_CONTAINER_DLL_remove (de->dt_head,
2462 de->dt_tail,
2463 dt);
2464 GNUNET_free (dt);
2369 } 2465 }
2370 if (NULL != de->heap_node) 2466 if (NULL != de->heap_node)
2371 { 2467 {
@@ -2481,7 +2577,6 @@ service_redirect_to_ip (void *cls,
2481 void *addr; 2577 void *addr;
2482 struct DestinationEntry *de; 2578 struct DestinationEntry *de;
2483 struct GNUNET_HashCode key; 2579 struct GNUNET_HashCode key;
2484 struct TunnelState *ts;
2485 2580
2486 /* validate and parse request */ 2581 /* validate and parse request */
2487 mlen = ntohs (message->size); 2582 mlen = ntohs (message->size);
@@ -2574,22 +2669,6 @@ service_redirect_to_ip (void *cls,
2574 1, GNUNET_NO); 2669 1, GNUNET_NO);
2575 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings) 2670 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2576 expire_destination (de); 2671 expire_destination (de);
2577
2578 /* setup tunnel to destination */
2579 ts = create_tunnel_to_destination (de,
2580 result_af);
2581 switch (result_af)
2582 {
2583 case AF_INET:
2584 ts->destination_ip.v4 = v4;
2585 break;
2586 case AF_INET6:
2587 ts->destination_ip.v6 = v6;
2588 break;
2589 default:
2590 GNUNET_assert (0);
2591 }
2592 /* we're done */
2593 GNUNET_SERVER_receive_done (client, GNUNET_OK); 2672 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2594} 2673}
2595 2674
@@ -2604,7 +2683,8 @@ service_redirect_to_ip (void *cls,
2604 * @param message redirection request (a `struct RedirectToPeerRequestMessage`) 2683 * @param message redirection request (a `struct RedirectToPeerRequestMessage`)
2605 */ 2684 */
2606static void 2685static void
2607service_redirect_to_service (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client, 2686service_redirect_to_service (void *cls,
2687 struct GNUNET_SERVER_Client *client,
2608 const struct GNUNET_MessageHeader *message) 2688 const struct GNUNET_MessageHeader *message)
2609{ 2689{
2610 const struct RedirectToServiceRequestMessage *msg; 2690 const struct RedirectToServiceRequestMessage *msg;
@@ -2615,6 +2695,7 @@ service_redirect_to_service (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Clien
2615 struct DestinationEntry *de; 2695 struct DestinationEntry *de;
2616 struct GNUNET_HashCode key; 2696 struct GNUNET_HashCode key;
2617 struct TunnelState *ts; 2697 struct TunnelState *ts;
2698 struct DestinationTunnel *dt;
2618 2699
2619 /* parse request */ 2700 /* parse request */
2620 msg = (const struct RedirectToServiceRequestMessage *) message; 2701 msg = (const struct RedirectToServiceRequestMessage *) message;
@@ -2670,7 +2751,13 @@ service_redirect_to_service (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Clien
2670 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us); 2751 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2671 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings) 2752 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2672 expire_destination (de); 2753 expire_destination (de);
2673 ts = create_tunnel_to_destination (de, 2754
2755 dt = GNUNET_new (struct DestinationTunnel);
2756 dt->destination = de;
2757 GNUNET_CONTAINER_DLL_insert (de->dt_head,
2758 de->dt_tail,
2759 dt);
2760 ts = create_tunnel_to_destination (dt,
2674 result_af); 2761 result_af);
2675 switch (result_af) 2762 switch (result_af)
2676 { 2763 {