aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-01-02 09:57:25 +0000
committerChristian Grothoff <christian@grothoff.org>2012-01-02 09:57:25 +0000
commit2b152f749e6274ab97baa09b9d1522803c76027f (patch)
treeea5e4857b6de87cb3ad79da334c6d61e213cd54a
parenta0f00b8f5726eccb6eab9bcf974c3e45ab572220 (diff)
downloadgnunet-2b152f749e6274ab97baa09b9d1522803c76027f.tar.gz
gnunet-2b152f749e6274ab97baa09b9d1522803c76027f.zip
-using new GNUNET_HELPER_ API inside of VPN, also eliminating bugs with partial writes as part of this
-rw-r--r--src/vpn/Makefile.am3
-rw-r--r--src/vpn/gnunet-daemon-exit.c283
-rw-r--r--src/vpn/gnunet-daemon-vpn-helper.c691
-rw-r--r--src/vpn/gnunet-daemon-vpn-helper.h76
-rw-r--r--src/vpn/gnunet-daemon-vpn.c656
-rw-r--r--src/vpn/gnunet-helper-vpn-api.c98
-rw-r--r--src/vpn/gnunet-helper-vpn-api.h110
7 files changed, 780 insertions, 1137 deletions
diff --git a/src/vpn/Makefile.am b/src/vpn/Makefile.am
index ecb01969b..bdfca7f2f 100644
--- a/src/vpn/Makefile.am
+++ b/src/vpn/Makefile.am
@@ -34,8 +34,6 @@ gnunet_helper_vpn_SOURCES = \
34 34
35gnunet_daemon_vpn_SOURCES = \ 35gnunet_daemon_vpn_SOURCES = \
36 gnunet-daemon-vpn.c gnunet-daemon-vpn.h \ 36 gnunet-daemon-vpn.c gnunet-daemon-vpn.h \
37 gnunet-daemon-vpn-helper.c gnunet-daemon-vpn-helper.h \
38 gnunet-helper-vpn-api.c gnunet-helper-vpn-api.h \
39 gnunet-vpn-checksum.c gnunet-vpn-checksum.h 37 gnunet-vpn-checksum.c gnunet-vpn-checksum.h
40gnunet_daemon_vpn_LDADD = \ 38gnunet_daemon_vpn_LDADD = \
41 $(top_builddir)/src/core/libgnunetcore.la \ 39 $(top_builddir)/src/core/libgnunetcore.la \
@@ -48,7 +46,6 @@ gnunet_daemon_vpn_LDADD = \
48 46
49gnunet_daemon_exit_SOURCES = \ 47gnunet_daemon_exit_SOURCES = \
50 gnunet-daemon-exit.c \ 48 gnunet-daemon-exit.c \
51 gnunet-helper-vpn-api.c gnunet-helper-vpn-api.h \
52 gnunet-vpn-checksum.c gnunet-vpn-checksum.h 49 gnunet-vpn-checksum.c gnunet-vpn-checksum.h
53gnunet_daemon_exit_LDADD = \ 50gnunet_daemon_exit_LDADD = \
54 $(top_builddir)/src/core/libgnunetcore.la \ 51 $(top_builddir)/src/core/libgnunetcore.la \
diff --git a/src/vpn/gnunet-daemon-exit.c b/src/vpn/gnunet-daemon-exit.c
index 5c450ecc6..ebe3ec61a 100644
--- a/src/vpn/gnunet-daemon-exit.c
+++ b/src/vpn/gnunet-daemon-exit.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2010 Christian Grothoff 3 (C) 2010, 2012 Christian Grothoff
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -33,11 +33,8 @@
33#include <string.h> 33#include <string.h>
34 34
35#include "gnunet-vpn-packet.h" 35#include "gnunet-vpn-packet.h"
36#include "gnunet-helper-vpn-api.h"
37#include "gnunet-vpn-checksum.h" 36#include "gnunet-vpn-checksum.h"
38 37
39GNUNET_SCHEDULER_TaskIdentifier shs_task;
40
41/** 38/**
42 * The handle to the configuration used throughout the process 39 * The handle to the configuration used throughout the process
43 */ 40 */
@@ -46,7 +43,12 @@ static const struct GNUNET_CONFIGURATION_Handle *cfg;
46/** 43/**
47 * The handle to the helper 44 * The handle to the helper
48 */ 45 */
49struct GNUNET_VPN_HELPER_Handle *helper_handle; 46static struct GNUNET_HELPER_Handle *helper_handle;
47
48/**
49 * Arguments to the exit helper.
50 */
51static char *exit_argv[7];
50 52
51/** 53/**
52 * Final status code. 54 * Final status code.
@@ -63,8 +65,11 @@ static struct GNUNET_MESH_Handle *mesh_handle;
63 * source-port and destination-port to a struct redirect_state 65 * source-port and destination-port to a struct redirect_state
64 */ 66 */
65static struct GNUNET_CONTAINER_MultiHashMap *udp_connections; 67static struct GNUNET_CONTAINER_MultiHashMap *udp_connections;
68
66static struct GNUNET_CONTAINER_Heap *udp_connections_heap; 69static struct GNUNET_CONTAINER_Heap *udp_connections_heap;
70
67static struct GNUNET_CONTAINER_MultiHashMap *tcp_connections; 71static struct GNUNET_CONTAINER_MultiHashMap *tcp_connections;
72
68static struct GNUNET_CONTAINER_Heap *tcp_connections_heap; 73static struct GNUNET_CONTAINER_Heap *tcp_connections_heap;
69 74
70/** 75/**
@@ -136,8 +141,7 @@ struct redirect_state
136 struct GNUNET_CONTAINER_MultiHashMap *hashmap; 141 struct GNUNET_CONTAINER_MultiHashMap *hashmap;
137 GNUNET_HashCode hash; 142 GNUNET_HashCode hash;
138 143
139 enum 144 enum { SERVICE, REMOTE } type;
140 { SERVICE, REMOTE } type;
141 145
142 /** 146 /**
143 * The source-address and -port of this connection 147 * The source-address and -port of this connection
@@ -146,9 +150,14 @@ struct redirect_state
146}; 150};
147 151
148/** 152/**
149 * This hashmaps saves interesting things about the configured services 153 * This hashmaps saves interesting things about the configured UDP services
150 */ 154 */
151static struct GNUNET_CONTAINER_MultiHashMap *udp_services; 155static struct GNUNET_CONTAINER_MultiHashMap *udp_services;
156
157/**
158 * This hashmaps saves interesting things about the configured TCP services
159 */
160
152static struct GNUNET_CONTAINER_MultiHashMap *tcp_services; 161static struct GNUNET_CONTAINER_MultiHashMap *tcp_services;
153 162
154struct tunnel_notify_queue 163struct tunnel_notify_queue
@@ -166,6 +175,7 @@ struct tunnel_state
166 struct GNUNET_MESH_TransmitHandle *th; 175 struct GNUNET_MESH_TransmitHandle *th;
167}; 176};
168 177
178
169/** 179/**
170 * Function that frees everything from a hashmap 180 * Function that frees everything from a hashmap
171 */ 181 */
@@ -184,17 +194,23 @@ static void
184cleanup (void *cls GNUNET_UNUSED, 194cleanup (void *cls GNUNET_UNUSED,
185 const struct GNUNET_SCHEDULER_TaskContext *tskctx) 195 const struct GNUNET_SCHEDULER_TaskContext *tskctx)
186{ 196{
187 GNUNET_assert (0 != (tskctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)); 197 unsigned int i;
188
189 GNUNET_CONTAINER_multihashmap_iterate (udp_connections, free_iterate, NULL);
190
191 GNUNET_CONTAINER_multihashmap_iterate (tcp_connections, free_iterate, NULL);
192 198
199 GNUNET_assert (0 != (tskctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN));
193 if (mesh_handle != NULL) 200 if (mesh_handle != NULL)
194 { 201 {
195 GNUNET_MESH_disconnect (mesh_handle); 202 GNUNET_MESH_disconnect (mesh_handle);
196 mesh_handle = NULL; 203 mesh_handle = NULL;
197 } 204 }
205 if (helper_handle != NULL)
206 {
207 GNUNET_HELPER_stop (helper_handle);
208 helper_handle = NULL;
209 }
210 GNUNET_CONTAINER_multihashmap_iterate (udp_connections, &free_iterate, NULL);
211 GNUNET_CONTAINER_multihashmap_iterate (tcp_connections, &free_iterate, NULL);
212 for (i=0;i<5;i++)
213 GNUNET_free_non_null (exit_argv[i]);
198} 214}
199 215
200static void * 216static void *
@@ -750,89 +766,7 @@ next:
750 while (proto != UDP); 766 while (proto != UDP);
751} 767}
752 768
753/**
754 * Start the helper-process
755 *
756 * If cls != NULL it is assumed that this function is called as a result of a dying
757 * helper. cls is then taken as handle to the old helper and is cleaned up.
758 */
759static void
760start_helper_and_schedule (void *cls,
761 const struct GNUNET_SCHEDULER_TaskContext *tc)
762{
763 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
764 return;
765
766 if (cls != NULL)
767 cleanup_helper (cls);
768 cls = NULL;
769
770 char *ifname;
771 char *ipv6addr;
772 char *ipv6prefix;
773 char *ipv4addr;
774 char *ipv4mask;
775
776 if (GNUNET_SYSERR ==
777 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IFNAME", &ifname))
778 {
779 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
780 "No entry 'IFNAME' in configuration!\n");
781 exit (1);
782 }
783
784 if (GNUNET_SYSERR ==
785 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6ADDR",
786 &ipv6addr))
787 {
788 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
789 "No entry 'IPV6ADDR' in configuration!\n");
790 exit (1);
791 }
792
793 if (GNUNET_SYSERR ==
794 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6PREFIX",
795 &ipv6prefix))
796 {
797 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
798 "No entry 'IPV6PREFIX' in configuration!\n");
799 exit (1);
800 }
801
802 if (GNUNET_SYSERR ==
803 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4ADDR",
804 &ipv4addr))
805 {
806 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
807 "No entry 'IPV4ADDR' in configuration!\n");
808 exit (1);
809 }
810
811 if (GNUNET_SYSERR ==
812 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4MASK",
813 &ipv4mask))
814 {
815 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
816 "No entry 'IPV4MASK' in configuration!\n");
817 exit (1);
818 }
819
820 /* Start the helper
821 * Messages get passed to the function message_token
822 * When the helper dies, this function will be called again with the
823 * helper_handle as cls.
824 */
825 helper_handle =
826 start_helper (ifname, ipv6addr, ipv6prefix, ipv4addr, ipv4mask,
827 "exit-gnunet", start_helper_and_schedule, message_token,
828 NULL);
829 769
830 GNUNET_free (ipv6addr);
831 GNUNET_free (ipv6prefix);
832 GNUNET_free (ipv4addr);
833 GNUNET_free (ipv4mask);
834 GNUNET_free (ifname);
835}
836 770
837static void 771static void
838prepare_ipv4_packet (size_t len, uint16_t pktlen, void *payload, 772prepare_ipv4_packet (size_t len, uint16_t pktlen, void *payload,
@@ -1068,7 +1002,6 @@ receive_tcp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1068 * At this point it would be possible to check against some kind of ACL. 1002 * At this point it would be possible to check against some kind of ACL.
1069 */ 1003 */
1070 1004
1071 char *buf;
1072 size_t len; 1005 size_t len;
1073 1006
1074 /* Prepare the state. 1007 /* Prepare the state.
@@ -1086,50 +1019,56 @@ receive_tcp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1086 len = 1019 len =
1087 sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) + 1020 sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) +
1088 sizeof (struct ip6_hdr) + pkt_len; 1021 sizeof (struct ip6_hdr) + pkt_len;
1089 buf = alloca (len);
1090
1091 memset (buf, 0, len);
1092
1093 switch (serv->version)
1094 { 1022 {
1095 case 4: 1023 char buf[len];
1096 prepare_ipv4_packet (len, pkt_len, pkt, IPPROTO_TCP, &serv->v4.ip4address,
1097 tunnel, state, (struct ip_pkt *) buf);
1098 break;
1099 case 6:
1100 prepare_ipv6_packet (len, pkt_len, pkt, IPPROTO_TCP, &serv->v6.ip6address,
1101 tunnel, state, (struct ip6_pkt *) buf);
1102
1103 break;
1104 default:
1105 GNUNET_assert (0);
1106 break;
1107 }
1108
1109 hash_redirect_info (&state->hash, &state->redirect_info,
1110 serv->version == 4 ? 4 : 16);
1111 1024
1112 if (GNUNET_NO == 1025 memset (buf, 0, len);
1113 GNUNET_CONTAINER_multihashmap_contains (tcp_connections, &state->hash)) 1026 switch (serv->version)
1114 { 1027 {
1115 GNUNET_CONTAINER_multihashmap_put (tcp_connections, &state->hash, state, 1028 case 4:
1116 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); 1029 prepare_ipv4_packet (len, pkt_len, pkt, IPPROTO_TCP, &serv->v4.ip4address,
1030 tunnel, state, (struct ip_pkt *) buf);
1031 break;
1032 case 6:
1033 prepare_ipv6_packet (len, pkt_len, pkt, IPPROTO_TCP, &serv->v6.ip6address,
1034 tunnel, state, (struct ip6_pkt *) buf);
1035
1036 break;
1037 default:
1038 GNUNET_assert (0);
1039 break;
1040 }
1117 1041
1118 state->heap_node = 1042 hash_redirect_info (&state->hash, &state->redirect_info,
1119 GNUNET_CONTAINER_heap_insert (tcp_connections_heap, state, 1043 serv->version == 4 ? 4 : 16);
1120 GNUNET_TIME_absolute_get ().abs_value); 1044
1045 if (GNUNET_NO ==
1046 GNUNET_CONTAINER_multihashmap_contains (tcp_connections, &state->hash))
1047 {
1048 GNUNET_CONTAINER_multihashmap_put (tcp_connections, &state->hash, state,
1049 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1050
1051 state->heap_node =
1052 GNUNET_CONTAINER_heap_insert (tcp_connections_heap, state,
1053 GNUNET_TIME_absolute_get ().abs_value);
1054
1055 if (GNUNET_CONTAINER_heap_get_size (tcp_connections_heap) >
1056 max_tcp_connections)
1057 GNUNET_SCHEDULER_add_now (collect_connections, tcp_connections_heap);
1058 }
1059 else
1060 GNUNET_free (state);
1121 1061
1122 if (GNUNET_CONTAINER_heap_get_size (tcp_connections_heap) > 1062 /* FIXME: here, flow-control with mesh would be nice to have... */
1123 max_tcp_connections) 1063 (void) GNUNET_HELPER_send (helper_handle,
1124 GNUNET_SCHEDULER_add_now (collect_connections, tcp_connections_heap); 1064 (const struct GNUNET_MessageHeader*) buf,
1065 GNUNET_YES,
1066 NULL, NULL);
1125 } 1067 }
1126 else
1127 GNUNET_free (state);
1128
1129 (void) GNUNET_DISK_file_write (helper_handle->fh_to_helper, buf, len);
1130 return GNUNET_YES; 1068 return GNUNET_YES;
1131} 1069}
1132 1070
1071
1133static int 1072static int
1134receive_tcp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, 1073receive_tcp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1135 void **tunnel_ctx GNUNET_UNUSED, 1074 void **tunnel_ctx GNUNET_UNUSED,
@@ -1197,7 +1136,11 @@ receive_tcp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1197 else 1136 else
1198 GNUNET_free (state); 1137 GNUNET_free (state);
1199 1138
1200 (void) GNUNET_DISK_file_write (helper_handle->fh_to_helper, buf, len); 1139 /* FIXME: here, flow-control with mesh would be nice to have... */
1140 (void) GNUNET_HELPER_send (helper_handle,
1141 (const struct GNUNET_MessageHeader*) buf,
1142 GNUNET_YES,
1143 NULL, NULL);
1201 return GNUNET_YES; 1144 return GNUNET_YES;
1202 1145
1203} 1146}
@@ -1271,7 +1214,10 @@ receive_udp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1271 else 1214 else
1272 GNUNET_free (state); 1215 GNUNET_free (state);
1273 1216
1274 (void) GNUNET_DISK_file_write (helper_handle->fh_to_helper, buf, len); 1217 (void) GNUNET_HELPER_send (helper_handle,
1218 (const struct GNUNET_MessageHeader*) buf,
1219 GNUNET_YES,
1220 NULL, NULL);
1275 return GNUNET_YES; 1221 return GNUNET_YES;
1276} 1222}
1277 1223
@@ -1374,7 +1320,10 @@ receive_udp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1374 else 1320 else
1375 GNUNET_free (state); 1321 GNUNET_free (state);
1376 1322
1377 (void) GNUNET_DISK_file_write (helper_handle->fh_to_helper, buf, len); 1323 (void) GNUNET_HELPER_send (helper_handle,
1324 (const struct GNUNET_MessageHeader*) buf,
1325 GNUNET_YES,
1326 NULL, NULL);
1378 return GNUNET_YES; 1327 return GNUNET_YES;
1379} 1328}
1380 1329
@@ -1430,6 +1379,7 @@ connect_to_mesh ()
1430} 1379}
1431 1380
1432 1381
1382
1433/** 1383/**
1434 * @brief Main function that will be run by the scheduler. 1384 * @brief Main function that will be run by the scheduler.
1435 * 1385 *
@@ -1443,10 +1393,14 @@ run (void *cls, char *const *args GNUNET_UNUSED,
1443 const char *cfgfile GNUNET_UNUSED, 1393 const char *cfgfile GNUNET_UNUSED,
1444 const struct GNUNET_CONFIGURATION_Handle *cfg_) 1394 const struct GNUNET_CONFIGURATION_Handle *cfg_)
1445{ 1395{
1446 cfg = cfg_; 1396 char *ifname;
1397 char *ipv6addr;
1398 char *ipv6prefix;
1399 char *ipv4addr;
1400 char *ipv4mask;
1447 1401
1402 cfg = cfg_;
1448 connect_to_mesh (); 1403 connect_to_mesh ();
1449
1450 udp_connections = GNUNET_CONTAINER_multihashmap_create (65536); 1404 udp_connections = GNUNET_CONTAINER_multihashmap_create (65536);
1451 udp_connections_heap = 1405 udp_connections_heap =
1452 GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); 1406 GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
@@ -1455,7 +1409,6 @@ run (void *cls, char *const *args GNUNET_UNUSED,
1455 GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); 1409 GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1456 udp_services = GNUNET_CONTAINER_multihashmap_create (65536); 1410 udp_services = GNUNET_CONTAINER_multihashmap_create (65536);
1457 tcp_services = GNUNET_CONTAINER_multihashmap_create (65536); 1411 tcp_services = GNUNET_CONTAINER_multihashmap_create (65536);
1458
1459 if (GNUNET_OK != 1412 if (GNUNET_OK !=
1460 GNUNET_CONFIGURATION_get_value_number (cfg, "exit", "MAX_UDP_CONNECTIONS", 1413 GNUNET_CONFIGURATION_get_value_number (cfg, "exit", "MAX_UDP_CONNECTIONS",
1461 &max_udp_connections)) 1414 &max_udp_connections))
@@ -1465,7 +1418,59 @@ run (void *cls, char *const *args GNUNET_UNUSED,
1465 &max_tcp_connections)) 1418 &max_tcp_connections))
1466 max_tcp_connections = 256; 1419 max_tcp_connections = 256;
1467 GNUNET_CONFIGURATION_iterate_sections (cfg, read_service_conf, NULL); 1420 GNUNET_CONFIGURATION_iterate_sections (cfg, read_service_conf, NULL);
1468 GNUNET_SCHEDULER_add_now (start_helper_and_schedule, NULL); 1421
1422 if (GNUNET_SYSERR ==
1423 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IFNAME", &ifname))
1424 {
1425 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1426 "No entry 'IFNAME' in configuration!\n");
1427 exit (1);
1428 }
1429
1430 if (GNUNET_SYSERR ==
1431 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6ADDR",
1432 &ipv6addr))
1433 {
1434 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1435 "No entry 'IPV6ADDR' in configuration!\n");
1436 exit (1);
1437 }
1438
1439 if (GNUNET_SYSERR ==
1440 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6PREFIX",
1441 &ipv6prefix))
1442 {
1443 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1444 "No entry 'IPV6PREFIX' in configuration!\n");
1445 exit (1);
1446 }
1447
1448 if (GNUNET_SYSERR ==
1449 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4ADDR",
1450 &ipv4addr))
1451 {
1452 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1453 "No entry 'IPV4ADDR' in configuration!\n");
1454 exit (1);
1455 }
1456
1457 if (GNUNET_SYSERR ==
1458 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4MASK",
1459 &ipv4mask))
1460 {
1461 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1462 "No entry 'IPV4MASK' in configuration!\n");
1463 exit (1);
1464 }
1465 exit_argv[0] = GNUNET_strdup ("exit-gnunet");
1466 exit_argv[1] = ifname;
1467 exit_argv[2] = ipv6addr;
1468 exit_argv[3] = ipv6prefix;
1469 exit_argv[4] = ipv4addr;
1470 exit_argv[5] = ipv4mask;
1471 exit_argv[6] = NULL;
1472 helper_handle = GNUNET_HELPER_start ("gnunet-helper-vpn", exit_argv,
1473 &message_token, NULL);
1469 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls); 1474 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
1470} 1475}
1471 1476
diff --git a/src/vpn/gnunet-daemon-vpn-helper.c b/src/vpn/gnunet-daemon-vpn-helper.c
deleted file mode 100644
index 3bb3aa262..000000000
--- a/src/vpn/gnunet-daemon-vpn-helper.c
+++ /dev/null
@@ -1,691 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010 Christian Grothoff
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file vpn/gnunet-daemon-vpn-helper.c
23 * @brief
24 * @author Philipp Toelke
25 */
26#include <platform.h>
27#include <gnunet_common.h>
28#include <gnunet_client_lib.h>
29#include <gnunet_os_lib.h>
30#include <gnunet_mesh_service.h>
31#include <gnunet_protocols.h>
32#include <gnunet_server_lib.h>
33#include <gnunet_container_lib.h>
34#include <block_dns.h>
35#include <gnunet_configuration_lib.h>
36#include <gnunet_applications.h>
37#include <gnunet_dns_service.h>
38
39#include "gnunet-daemon-vpn.h"
40#include "gnunet-daemon-vpn-helper.h"
41#include "gnunet-vpn-packet.h"
42#include "gnunet-vpn-checksum.h"
43#include "gnunet-helper-vpn-api.h"
44
45struct GNUNET_VPN_HELPER_Handle *helper_handle;
46
47extern struct GNUNET_CLIENT_TransmitHandle *dns_transmit_handle;
48
49/**
50 * The tunnels that will be used to send tcp- and udp-packets
51 */
52static struct GNUNET_MESH_Tunnel *tcp_tunnel;
53static struct GNUNET_MESH_Tunnel *udp_tunnel;
54
55/**
56 * Start the helper-process
57 *
58 * If cls != NULL it is assumed that this function is called as a result of a dying
59 * helper. cls is then taken as handle to the old helper and is cleaned up.
60 * {{{
61 */
62void
63start_helper_and_schedule (void *cls,
64 const struct GNUNET_SCHEDULER_TaskContext *tc)
65{
66 shs_task = GNUNET_SCHEDULER_NO_TASK;
67 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
68 return;
69
70 if (cls != NULL)
71 cleanup_helper (cls);
72 cls = NULL;
73
74 char *ifname;
75 char *ipv6addr;
76 char *ipv6prefix;
77 char *ipv4addr;
78 char *ipv4mask;
79
80 if (GNUNET_SYSERR ==
81 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IFNAME", &ifname))
82 {
83 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
84 "No entry 'IFNAME' in configuration!\n");
85 exit (1);
86 }
87
88 if (GNUNET_SYSERR ==
89 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR", &ipv6addr))
90 {
91 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
92 "No entry 'IPV6ADDR' in configuration!\n");
93 exit (1);
94 }
95
96 if (GNUNET_SYSERR ==
97 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6PREFIX",
98 &ipv6prefix))
99 {
100 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
101 "No entry 'IPV6PREFIX' in configuration!\n");
102 exit (1);
103 }
104
105 if (GNUNET_SYSERR ==
106 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR", &ipv4addr))
107 {
108 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
109 "No entry 'IPV4ADDR' in configuration!\n");
110 exit (1);
111 }
112
113 if (GNUNET_SYSERR ==
114 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK", &ipv4mask))
115 {
116 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
117 "No entry 'IPV4MASK' in configuration!\n");
118 exit (1);
119 }
120
121 /* Start the helper
122 * Messages get passed to the function message_token
123 * When the helper dies, this function will be called again with the
124 * helper_handle as cls.
125 */
126 helper_handle =
127 start_helper (ifname, ipv6addr, ipv6prefix, ipv4addr, ipv4mask,
128 "vpn-gnunet", start_helper_and_schedule, message_token,
129 NULL);
130
131 GNUNET_free (ipv6addr);
132 GNUNET_free (ipv6prefix);
133 GNUNET_free (ipv4addr);
134 GNUNET_free (ipv4mask);
135 GNUNET_free (ifname);
136
137 /* Tell the dns-service to rehijack the dns-port
138 * The routing-table gets flushed if an interface disappears.
139 */
140 GNUNET_DNS_restart_hijack (dns_handle);
141 GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
142 helper_handle->fh_to_helper, &helper_write,
143 NULL);
144}
145
146/*}}}*/
147
148static void *
149initialize_tunnel_state (int addrlen, struct GNUNET_MESH_TransmitHandle *th)
150{
151 struct tunnel_state *ts = GNUNET_malloc (sizeof *ts);
152
153 ts->addrlen = addrlen;
154 ts->th = th;
155 return ts;
156}
157
158/**
159 * Send an dns-answer-packet to the helper
160 */
161void
162helper_write (void *cls GNUNET_UNUSED,
163 const struct GNUNET_SCHEDULER_TaskContext *tsdkctx)
164{
165 if (tsdkctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)
166 return;
167
168 struct answer_packet_list *ans = answer_proc_head;
169
170 if (NULL == ans)
171 return;
172
173 size_t len = ntohs (ans->pkt.hdr.size);
174
175 GNUNET_assert (ans->pkt.subtype == GNUNET_DNS_ANSWER_TYPE_IP);
176
177 GNUNET_assert (20 == sizeof (struct ip_hdr));
178 GNUNET_assert (8 == sizeof (struct udp_pkt));
179
180 size_t data_len = len - sizeof (struct answer_packet) + 1;
181
182 void *buf;
183 size_t pkt_len;
184
185 if (ans->pkt.addrlen == 16)
186 {
187 size_t net_len =
188 sizeof (struct ip6_hdr) + sizeof (struct udp_dns) + data_len;
189 pkt_len =
190 sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) +
191 net_len;
192
193 struct ip6_udp_dns *pkt = alloca (pkt_len);
194
195 GNUNET_assert (pkt != NULL);
196 memset (pkt, 0, pkt_len);
197
198 /* set the gnunet-header */
199 pkt->shdr.size = htons (pkt_len);
200 pkt->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
201
202 /* set the tun-header (no flags and ethertype of IPv4) */
203 pkt->tun.flags = 0;
204 pkt->tun.type = htons (0x86dd);
205
206 memcpy (&pkt->ip6_hdr.sadr, ans->pkt.from, 16);
207 memcpy (&pkt->ip6_hdr.dadr, ans->pkt.to, 16);
208
209 /* set the udp-header */
210 pkt->udp_dns.udp_hdr.spt = htons (53);
211 pkt->udp_dns.udp_hdr.dpt = ans->pkt.dst_port;
212 pkt->udp_dns.udp_hdr.len = htons (net_len - sizeof (struct ip6_hdr));
213 pkt->udp_dns.udp_hdr.crc = 0;
214 uint32_t sum = 0;
215
216 sum = calculate_checksum_update (sum, (uint16_t *) & pkt->ip6_hdr.sadr, 16);
217 sum = calculate_checksum_update (sum, (uint16_t *) & pkt->ip6_hdr.dadr, 16);
218 uint32_t tmp = (pkt->udp_dns.udp_hdr.len & 0xffff);
219
220 sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4);
221 tmp = htons (((pkt->ip6_hdr.nxthdr & 0x00ff)));
222 sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4);
223
224 sum =
225 calculate_checksum_update (sum, (uint16_t *) & pkt->udp_dns.udp_hdr,
226 ntohs (net_len - sizeof (struct ip6_hdr)));
227 pkt->udp_dns.udp_hdr.crc = calculate_checksum_end (sum);
228
229 pkt->ip6_hdr.version = 6;
230 pkt->ip6_hdr.paylgth = net_len - sizeof (struct ip6_hdr);
231 pkt->ip6_hdr.nxthdr = IPPROTO_UDP;
232 pkt->ip6_hdr.hoplmt = 0xff;
233
234 memcpy (&pkt->udp_dns.data, ans->pkt.data, data_len);
235 buf = pkt;
236 }
237 else if (ans->pkt.addrlen == 4)
238 {
239 size_t net_len =
240 sizeof (struct ip_hdr) + sizeof (struct udp_dns) + data_len;
241 pkt_len =
242 sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) +
243 net_len;
244
245 struct ip_udp_dns *pkt = alloca (pkt_len);
246
247 GNUNET_assert (pkt != NULL);
248 memset (pkt, 0, pkt_len);
249
250 /* set the gnunet-header */
251 pkt->shdr.size = htons (pkt_len);
252 pkt->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
253
254 /* set the tun-header (no flags and ethertype of IPv4) */
255 pkt->tun.flags = 0;
256 pkt->tun.type = htons (0x0800);
257
258 /* set the ip-header */
259 pkt->ip_hdr.version = 4;
260 pkt->ip_hdr.hdr_lngth = 5;
261 pkt->ip_hdr.diff_serv = 0;
262 pkt->ip_hdr.tot_lngth = htons (net_len);
263 pkt->ip_hdr.ident = 0;
264 pkt->ip_hdr.flags = 0;
265 pkt->ip_hdr.frag_off = 0;
266 pkt->ip_hdr.ttl = 255;
267 pkt->ip_hdr.proto = IPPROTO_UDP;
268 pkt->ip_hdr.chks = 0; /* Will be calculated later */
269
270 memcpy (&pkt->ip_hdr.sadr, ans->pkt.from, 4);
271 memcpy (&pkt->ip_hdr.dadr, ans->pkt.to, 4);
272
273 pkt->ip_hdr.chks =
274 calculate_ip_checksum ((uint16_t *) & pkt->ip_hdr, 5 * 4);
275
276 /* set the udp-header */
277 pkt->udp_dns.udp_hdr.spt = htons (53);
278 pkt->udp_dns.udp_hdr.dpt = ans->pkt.dst_port;
279 pkt->udp_dns.udp_hdr.len = htons (net_len - sizeof (struct ip_hdr));
280 pkt->udp_dns.udp_hdr.crc = 0; /* Optional for IPv4 */
281
282 memcpy (&pkt->udp_dns.data, ans->pkt.data, data_len);
283 buf = pkt;
284 }
285 else
286 {
287 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Wrong addrlen = %d\n",
288 ans->pkt.addrlen);
289 GNUNET_assert (0);
290 return; /* convince compiler that we're done here */
291 }
292
293 GNUNET_CONTAINER_DLL_remove (answer_proc_head, answer_proc_tail, ans);
294 GNUNET_free (ans);
295
296 if (GNUNET_DISK_file_write (helper_handle->fh_to_helper, buf, pkt_len) < 0)
297 {
298 cleanup_helper (helper_handle);
299 GNUNET_SCHEDULER_add_now (start_helper_and_schedule, NULL);
300 return;
301 }
302
303 /* if more packets are available, reschedule */
304 if (answer_proc_head != NULL)
305 GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
306 helper_handle->fh_to_helper, &helper_write,
307 NULL);
308}
309
310/**
311 * Receive packets from the helper-process
312 */
313void
314message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
315 const struct GNUNET_MessageHeader *message)
316{
317 GNUNET_assert (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_HELPER);
318
319 struct tun_pkt *pkt_tun = (struct tun_pkt *) message;
320 GNUNET_HashCode *key;
321
322 /* ethertype is ipv6 */
323 if (ntohs (pkt_tun->tun.type) == 0x86dd)
324 {
325 struct ip6_pkt *pkt6 = (struct ip6_pkt *) message;
326
327 GNUNET_assert (pkt6->ip6_hdr.version == 6);
328 struct ip6_tcp *pkt6_tcp;
329 struct ip6_udp *pkt6_udp;
330 struct ip6_icmp *pkt6_icmp;
331
332 pkt6_udp = NULL; /* make compiler happy */
333 switch (pkt6->ip6_hdr.nxthdr)
334 {
335 case IPPROTO_UDP:
336 pkt6_udp = (struct ip6_udp *) pkt6;
337 /* Send dns-packets to the service-dns */
338 if (ntohs (pkt6_udp->udp_hdr.dpt) == 53)
339 {
340 /* 9 = 8 for the udp-header + 1 for the unsigned char data[1]; */
341 GNUNET_DNS_queue_request_v6 (dns_handle,
342 &pkt6->ip6_hdr.dadr,
343 &pkt6->ip6_hdr.sadr,
344 ntohs (pkt6_udp->udp_hdr.spt),
345 ntohs (pkt6_udp->udp_hdr.len) - 8,
346 (const void*) pkt6_udp->data);
347
348 break;
349 }
350 /* fall through */
351 case IPPROTO_TCP:
352 pkt6_tcp = (struct ip6_tcp *) pkt6;
353
354 if ((key = address6_mapping_exists (&pkt6->ip6_hdr.dadr)) != NULL)
355 {
356 struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
357
358 GNUNET_assert (me != NULL);
359 GNUNET_free (key);
360
361 size_t size =
362 sizeof (struct GNUNET_MESH_Tunnel *) +
363 sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) +
364 ntohs (pkt6->ip6_hdr.paylgth);
365
366 struct GNUNET_MESH_Tunnel **cls = GNUNET_malloc (size);
367 struct GNUNET_MessageHeader *hdr =
368 (struct GNUNET_MessageHeader *) (cls + 1);
369 GNUNET_HashCode *hc = (GNUNET_HashCode *) (hdr + 1);
370
371 hdr->size =
372 htons (sizeof (struct GNUNET_MessageHeader) +
373 sizeof (GNUNET_HashCode) + ntohs (pkt6->ip6_hdr.paylgth));
374
375 GNUNET_MESH_ApplicationType app_type = 0; /* fix compiler uninitialized warning... */
376
377 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "me->addrlen is %d\n",
378 me->addrlen);
379 if (me->addrlen == 0)
380 {
381 /* This is a mapping to a gnunet-service */
382 memcpy (hc, &me->desc.service_descriptor, sizeof (GNUNET_HashCode));
383
384 if (IPPROTO_UDP == pkt6->ip6_hdr.nxthdr &&
385 (me->desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_UDP)) &&
386 (port_in_ports (me->desc.ports, pkt6_udp->udp_hdr.dpt) ||
387 testBit (me->additional_ports, ntohs (pkt6_udp->udp_hdr.dpt))))
388 {
389 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP);
390
391 memcpy (hc + 1, &pkt6_udp->udp_hdr, ntohs (pkt6_udp->udp_hdr.len));
392
393 }
394 else if (IPPROTO_TCP == pkt6->ip6_hdr.nxthdr &&
395 (me->desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_TCP))
396 && (port_in_ports (me->desc.ports, pkt6_tcp->tcp_hdr.dpt)))
397 {
398 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP);
399
400 memcpy (hc + 1, &pkt6_tcp->tcp_hdr, ntohs (pkt6->ip6_hdr.paylgth));
401
402 }
403 else
404 {
405 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pip: %d\n",
406 port_in_ports (me->desc.ports, pkt6_tcp->tcp_hdr.dpt));
407 GNUNET_assert (0);
408 }
409 if (me->tunnel == NULL && NULL != cls)
410 {
411 *cls =
412 GNUNET_MESH_tunnel_create (mesh_handle,
413 initialize_tunnel_state (16, NULL),
414 &send_pkt_to_peer, NULL, cls);
415
416 GNUNET_MESH_peer_request_connect_add (*cls,
417 (struct GNUNET_PeerIdentity *)
418 &me->desc.peer);
419 me->tunnel = *cls;
420 }
421 else if (NULL != cls)
422 {
423 *cls = me->tunnel;
424 send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL);
425 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
426 "Queued to send IPv6 to peer %x, type %d\n",
427 *((unsigned int *) &me->desc.peer), ntohs (hdr->type));
428 }
429 }
430 else
431 {
432 /* This is a mapping to a "real" address */
433 struct remote_addr *s = (struct remote_addr *) hc;
434
435 s->addrlen = me->addrlen;
436 memcpy (s->addr, me->addr, me->addrlen);
437 s->proto = pkt6->ip6_hdr.nxthdr;
438 if (s->proto == IPPROTO_UDP)
439 {
440 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP);
441 memcpy (hc + 1, &pkt6_udp->udp_hdr, ntohs (pkt6_udp->udp_hdr.len));
442 app_type = GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY;
443 if (NULL != udp_tunnel)
444 me->tunnel = udp_tunnel;
445 }
446 else if (s->proto == IPPROTO_TCP)
447 {
448 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP);
449 memcpy (hc + 1, &pkt6_tcp->tcp_hdr, ntohs (pkt6->ip6_hdr.paylgth));
450 app_type = GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY;
451 if (NULL != tcp_tunnel)
452 me->tunnel = tcp_tunnel;
453 }
454 else
455 {
456 GNUNET_assert (0);
457 }
458 if (me->tunnel == NULL && NULL != cls)
459 {
460 *cls =
461 GNUNET_MESH_tunnel_create (mesh_handle,
462 initialize_tunnel_state (16, NULL),
463 &send_pkt_to_peer, NULL, cls);
464
465 GNUNET_MESH_peer_request_connect_by_type (*cls, app_type);
466 me->tunnel = *cls;
467 if (GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY == app_type)
468 udp_tunnel = *cls;
469 else if (GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY == app_type)
470 tcp_tunnel = *cls;
471 }
472 else if (NULL != cls)
473 {
474 *cls = me->tunnel;
475 send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL);
476 }
477 }
478 }
479 else
480 {
481 char pbuf[INET6_ADDRSTRLEN];
482 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
483 "Packet to %s, which has no mapping\n",
484 inet_ntop (AF_INET6,
485 &pkt6->ip6_hdr.dadr,
486 pbuf,
487 sizeof (pbuf)));
488 }
489 break;
490 case 0x3a:
491 /* ICMPv6 */
492 pkt6_icmp = (struct ip6_icmp *) pkt6;
493 /* If this packet is an icmp-echo-request and a mapping exists, answer */
494 if (pkt6_icmp->icmp_hdr.type == 0x80 &&
495 (key = address6_mapping_exists (&pkt6->ip6_hdr.dadr)) != NULL)
496 {
497 GNUNET_free (key);
498 pkt6_icmp = GNUNET_malloc (ntohs (pkt6->shdr.size));
499 memcpy (pkt6_icmp, pkt6, ntohs (pkt6->shdr.size));
500 GNUNET_SCHEDULER_add_now (&send_icmp6_response, pkt6_icmp);
501 }
502 break;
503 }
504 }
505 /* ethertype is ipv4 */
506 else if (ntohs (pkt_tun->tun.type) == 0x0800)
507 {
508 struct ip_pkt *pkt = (struct ip_pkt *) message;
509 struct ip_udp *udp = (struct ip_udp *) message;
510 struct ip_tcp *pkt_tcp;
511 struct ip_udp *pkt_udp;
512 struct ip_icmp *pkt_icmp;
513
514 GNUNET_assert (pkt->ip_hdr.version == 4);
515
516 /* Send dns-packets to the service-dns */
517 if (pkt->ip_hdr.proto == IPPROTO_UDP && ntohs (udp->udp_hdr.dpt) == 53)
518 {
519 GNUNET_DNS_queue_request_v4 (dns_handle,
520 &pkt->ip_hdr.dadr,
521 &pkt->ip_hdr.sadr,
522 ntohs (udp->udp_hdr.spt),
523 ntohs (udp->udp_hdr.len) - 8,
524 (const void*) udp->data);
525 }
526 else
527 {
528 uint32_t dadr = pkt->ip_hdr.dadr.s_addr;
529 unsigned char *c = (unsigned char *) &dadr;
530
531 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Packet to %d.%d.%d.%d, proto %x\n",
532 c[0], c[1], c[2], c[3], pkt->ip_hdr.proto);
533 switch (pkt->ip_hdr.proto)
534 {
535 case IPPROTO_TCP:
536 case IPPROTO_UDP:
537 pkt_tcp = (struct ip_tcp *) pkt;
538 pkt_udp = (struct ip_udp *) pkt;
539
540 if ((key = address4_mapping_exists (dadr)) != NULL)
541 {
542 struct map_entry *me =
543 GNUNET_CONTAINER_multihashmap_get (hashmap, key);
544 GNUNET_assert (me != NULL);
545 GNUNET_free (key);
546
547 size_t size =
548 sizeof (struct GNUNET_MESH_Tunnel *) +
549 sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) +
550 ntohs (pkt->ip_hdr.tot_lngth) - 4 * pkt->ip_hdr.hdr_lngth;
551
552 struct GNUNET_MESH_Tunnel **cls = GNUNET_malloc (size);
553 struct GNUNET_MessageHeader *hdr =
554 (struct GNUNET_MessageHeader *) (cls + 1);
555 GNUNET_HashCode *hc = (GNUNET_HashCode *) (hdr + 1);
556
557 hdr->size =
558 htons (sizeof (struct GNUNET_MessageHeader) +
559 sizeof (GNUNET_HashCode) + ntohs (pkt->ip_hdr.tot_lngth) -
560 4 * pkt->ip_hdr.hdr_lngth);
561
562 GNUNET_MESH_ApplicationType app_type = 0; /* make compiler happy */
563
564 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "me->addrlen is %d\n",
565 me->addrlen);
566 if (me->addrlen == 0)
567 {
568 /* This is a mapping to a gnunet-service */
569 memcpy (hc, &me->desc.service_descriptor, sizeof (GNUNET_HashCode));
570
571 if ((IPPROTO_UDP == pkt->ip_hdr.proto) &&
572 (me->desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_UDP)) &&
573 (port_in_ports (me->desc.ports, pkt_udp->udp_hdr.dpt) ||
574 testBit (me->additional_ports, ntohs (pkt_udp->udp_hdr.dpt))))
575 {
576 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP);
577
578 memcpy (hc + 1, &pkt_udp->udp_hdr, ntohs (pkt_udp->udp_hdr.len));
579
580 }
581 else if ((IPPROTO_TCP == pkt->ip_hdr.proto) &&
582 (me->
583 desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_TCP))
584 && (port_in_ports (me->desc.ports, pkt_tcp->tcp_hdr.dpt)))
585 {
586 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP);
587
588 memcpy (hc + 1, &pkt_tcp->tcp_hdr,
589 ntohs (pkt->ip_hdr.tot_lngth) -
590 4 * pkt->ip_hdr.hdr_lngth);
591
592 }
593 if (me->tunnel == NULL && NULL != cls)
594 {
595 *cls =
596 GNUNET_MESH_tunnel_create (mesh_handle,
597 initialize_tunnel_state (4, NULL),
598 send_pkt_to_peer, NULL, cls);
599 GNUNET_MESH_peer_request_connect_add (*cls,
600 (struct GNUNET_PeerIdentity
601 *) &me->desc.peer);
602 me->tunnel = *cls;
603 }
604 else if (NULL != cls)
605 {
606 *cls = me->tunnel;
607 send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL);
608 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
609 "Queued to send IPv4 to peer %x, type %d\n",
610 *((unsigned int *) &me->desc.peer),
611 ntohs (hdr->type));
612 }
613 }
614 else
615 {
616 /* This is a mapping to a "real" address */
617 struct remote_addr *s = (struct remote_addr *) hc;
618
619 s->addrlen = me->addrlen;
620 memcpy (s->addr, me->addr, me->addrlen);
621 s->proto = pkt->ip_hdr.proto;
622 if (s->proto == IPPROTO_UDP)
623 {
624 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP);
625 memcpy (hc + 1, &pkt_udp->udp_hdr, ntohs (pkt_udp->udp_hdr.len));
626 app_type = GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY;
627 }
628 else if (s->proto == IPPROTO_TCP)
629 {
630 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP);
631 memcpy (hc + 1, &pkt_tcp->tcp_hdr,
632 ntohs (pkt->ip_hdr.tot_lngth) -
633 4 * pkt->ip_hdr.hdr_lngth);
634 app_type = GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY;
635 }
636 else
637 GNUNET_assert (0);
638 if (me->tunnel == NULL && NULL != cls)
639 {
640 *cls =
641 GNUNET_MESH_tunnel_create (mesh_handle,
642 initialize_tunnel_state (4, NULL),
643 send_pkt_to_peer, NULL, cls);
644
645 GNUNET_MESH_peer_request_connect_by_type (*cls, app_type);
646 me->tunnel = *cls;
647 }
648 else if (NULL != cls)
649 {
650 *cls = me->tunnel;
651 send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL);
652 }
653 }
654 }
655 else
656 {
657 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
658 "Packet to %x which has no mapping\n", dadr);
659 }
660 break;
661 case 0x01:
662 /* ICMP */
663 pkt_icmp = (struct ip_icmp *) pkt;
664 if (pkt_icmp->icmp_hdr.type == 0x8 &&
665 (key = address4_mapping_exists (dadr)) != NULL)
666 {
667 GNUNET_free (key);
668 pkt_icmp = GNUNET_malloc (ntohs (pkt->shdr.size));
669 memcpy (pkt_icmp, pkt, ntohs (pkt->shdr.size));
670 GNUNET_SCHEDULER_add_now (&send_icmp4_response, pkt_icmp);
671 }
672 break;
673 }
674 }
675 }
676}
677
678void
679write_to_helper (void *buf, size_t len)
680{
681 (void) GNUNET_DISK_file_write (helper_handle->fh_to_helper, buf, len);
682}
683
684void
685schedule_helper_write (struct GNUNET_TIME_Relative time, void *cls)
686{
687 if (GNUNET_SCHEDULER_NO_TASK != shs_task)
688 return;
689 GNUNET_SCHEDULER_add_write_file (time, helper_handle->fh_to_helper,
690 &helper_write, cls);
691}
diff --git a/src/vpn/gnunet-daemon-vpn-helper.h b/src/vpn/gnunet-daemon-vpn-helper.h
deleted file mode 100644
index 7329e45ff..000000000
--- a/src/vpn/gnunet-daemon-vpn-helper.h
+++ /dev/null
@@ -1,76 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010 Christian Grothoff
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file vpn/gnunet-daemon-vpn-helper.h
23 * @brief
24 * @author Philipp Toelke
25 */
26#ifndef GNUNET_DAEMON_VPN_HELPER_H
27#define GNUNET_DAEMON_VPN_HELPER_H
28
29#include "gnunet-helper-vpn-api.h"
30
31/**
32 * Handle to the helper. contains filedescriptors and such
33 */
34extern struct GNUNET_VPN_HELPER_Handle *helper_handle;
35
36extern GNUNET_SCHEDULER_TaskIdentifier shs_task;
37
38/**
39 * Start the helper-process
40 */
41void
42start_helper_and_schedule (void *cls,
43 const struct GNUNET_SCHEDULER_TaskContext *tc);
44
45/**
46 * Restart the helper-process
47 */
48void
49restart_helper (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tskctx);
50
51/**
52 * Read from the helper-process
53 */
54void
55helper_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tsdkctx);
56
57/**
58 * Send an dns-answer-packet to the helper
59 */
60void
61helper_write (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tsdkctx);
62
63/**
64 * Receive packets from the helper-process
65 */
66void
67message_token (void *cls, void *client,
68 const struct GNUNET_MessageHeader *message);
69
70void
71write_to_helper (void *buf, size_t len);
72
73void
74schedule_helper_write (struct GNUNET_TIME_Relative, void *cls);
75
76#endif /* end of include guard: GNUNET-DAEMON-VPN-HELPER_H */
diff --git a/src/vpn/gnunet-daemon-vpn.c b/src/vpn/gnunet-daemon-vpn.c
index 7d303ecd5..35db8af7b 100644
--- a/src/vpn/gnunet-daemon-vpn.c
+++ b/src/vpn/gnunet-daemon-vpn.c
@@ -35,7 +35,6 @@
35#include "gnunet_container_lib.h" 35#include "gnunet_container_lib.h"
36#include "gnunet_constants.h" 36#include "gnunet_constants.h"
37#include <block_dns.h> 37#include <block_dns.h>
38#include "gnunet-daemon-vpn-helper.h"
39#include "gnunet_dns_service.h" 38#include "gnunet_dns_service.h"
40#include "gnunet-daemon-vpn.h" 39#include "gnunet-daemon-vpn.h"
41#include "gnunet-vpn-checksum.h" 40#include "gnunet-vpn-checksum.h"
@@ -45,6 +44,16 @@ struct GNUNET_MESH_Handle *mesh_handle;
45struct GNUNET_CONTAINER_MultiHashMap *hashmap; 44struct GNUNET_CONTAINER_MultiHashMap *hashmap;
46static struct GNUNET_CONTAINER_Heap *heap; 45static struct GNUNET_CONTAINER_Heap *heap;
47 46
47/**
48 * The handle to the helper
49 */
50static struct GNUNET_HELPER_Handle *helper_handle;
51
52/**
53 * Arguments to the exit helper.
54 */
55static char *vpn_argv[7];
56
48struct GNUNET_DNS_Handle *dns_handle; 57struct GNUNET_DNS_Handle *dns_handle;
49 58
50struct answer_packet_list *answer_proc_head; 59struct answer_packet_list *answer_proc_head;
@@ -82,6 +91,14 @@ GNUNET_SCHEDULER_TaskIdentifier shs_task;
82 91
83 92
84/** 93/**
94 * The tunnels that will be used to send tcp- and udp-packets
95 */
96static struct GNUNET_MESH_Tunnel *tcp_tunnel;
97static struct GNUNET_MESH_Tunnel *udp_tunnel;
98
99
100
101/**
85 * Sets a bit active in a bitArray. 102 * Sets a bit active in a bitArray.
86 * 103 *
87 * @param bitArray memory area to set the bit in 104 * @param bitArray memory area to set the bit in
@@ -129,11 +146,9 @@ static void
129cleanup (void *cls GNUNET_UNUSED, 146cleanup (void *cls GNUNET_UNUSED,
130 const struct GNUNET_SCHEDULER_TaskContext *tskctx) 147 const struct GNUNET_SCHEDULER_TaskContext *tskctx)
131{ 148{
132 GNUNET_assert (0 != (tskctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)); 149 unsigned int i;
133
134 /* stop the helper */
135 cleanup_helper (helper_handle);
136 150
151 GNUNET_assert (0 != (tskctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN));
137 /* close the connection to the service-dns */ 152 /* close the connection to the service-dns */
138 GNUNET_DNS_disconnect (dns_handle); 153 GNUNET_DNS_disconnect (dns_handle);
139 if (mesh_handle != NULL) 154 if (mesh_handle != NULL)
@@ -141,6 +156,11 @@ cleanup (void *cls GNUNET_UNUSED,
141 GNUNET_MESH_disconnect (mesh_handle); 156 GNUNET_MESH_disconnect (mesh_handle);
142 mesh_handle = NULL; 157 mesh_handle = NULL;
143 } 158 }
159 if (helper_handle != NULL)
160 {
161 GNUNET_HELPER_stop (helper_handle);
162 helper_handle = NULL;
163 }
144 if (GNUNET_SCHEDULER_NO_TASK != shs_task) 164 if (GNUNET_SCHEDULER_NO_TASK != shs_task)
145 { 165 {
146 GNUNET_SCHEDULER_cancel (shs_task); 166 GNUNET_SCHEDULER_cancel (shs_task);
@@ -151,6 +171,8 @@ cleanup (void *cls GNUNET_UNUSED,
151 GNUNET_SCHEDULER_cancel (conn_task); 171 GNUNET_SCHEDULER_cancel (conn_task);
152 conn_task = GNUNET_SCHEDULER_NO_TASK; 172 conn_task = GNUNET_SCHEDULER_NO_TASK;
153 } 173 }
174 for (i=0;i<5;i++)
175 GNUNET_free_non_null (vpn_argv[i]);
154} 176}
155 177
156/*}}}*/ 178/*}}}*/
@@ -210,6 +232,532 @@ address4_mapping_exists (uint32_t addr)
210 } 232 }
211} 233}
212 234
235
236static void *
237initialize_tunnel_state (int addrlen, struct GNUNET_MESH_TransmitHandle *th)
238{
239 struct tunnel_state *ts = GNUNET_malloc (sizeof *ts);
240
241 ts->addrlen = addrlen;
242 ts->th = th;
243 return ts;
244}
245
246/**
247 * Send an dns-answer-packet to the helper
248 */
249void
250helper_write (void *cls GNUNET_UNUSED,
251 int status)
252{
253 struct answer_packet_list *ans = answer_proc_head;
254
255 if (NULL == ans)
256 return;
257 if (GNUNET_SYSERR == status)
258 return;
259
260 size_t len = ntohs (ans->pkt.hdr.size);
261
262 GNUNET_assert (ans->pkt.subtype == GNUNET_DNS_ANSWER_TYPE_IP);
263
264 GNUNET_assert (20 == sizeof (struct ip_hdr));
265 GNUNET_assert (8 == sizeof (struct udp_pkt));
266
267 size_t data_len = len - sizeof (struct answer_packet) + 1;
268
269 size_t pkt_len;
270
271 if (ans->pkt.addrlen == 16)
272 {
273 size_t net_len =
274 sizeof (struct ip6_hdr) + sizeof (struct udp_dns) + data_len;
275 pkt_len =
276 sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) +
277 net_len;
278
279 struct ip6_udp_dns *pkt = alloca (pkt_len);
280
281 GNUNET_assert (pkt != NULL);
282 memset (pkt, 0, pkt_len);
283
284 /* set the gnunet-header */
285 pkt->shdr.size = htons (pkt_len);
286 pkt->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
287
288 /* set the tun-header (no flags and ethertype of IPv4) */
289 pkt->tun.flags = 0;
290 pkt->tun.type = htons (0x86dd);
291
292 memcpy (&pkt->ip6_hdr.sadr, ans->pkt.from, 16);
293 memcpy (&pkt->ip6_hdr.dadr, ans->pkt.to, 16);
294
295 /* set the udp-header */
296 pkt->udp_dns.udp_hdr.spt = htons (53);
297 pkt->udp_dns.udp_hdr.dpt = ans->pkt.dst_port;
298 pkt->udp_dns.udp_hdr.len = htons (net_len - sizeof (struct ip6_hdr));
299 pkt->udp_dns.udp_hdr.crc = 0;
300 uint32_t sum = 0;
301
302 sum = calculate_checksum_update (sum, (uint16_t *) & pkt->ip6_hdr.sadr, 16);
303 sum = calculate_checksum_update (sum, (uint16_t *) & pkt->ip6_hdr.dadr, 16);
304 uint32_t tmp = (pkt->udp_dns.udp_hdr.len & 0xffff);
305
306 sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4);
307 tmp = htons (((pkt->ip6_hdr.nxthdr & 0x00ff)));
308 sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4);
309
310 sum =
311 calculate_checksum_update (sum, (uint16_t *) & pkt->udp_dns.udp_hdr,
312 ntohs (net_len - sizeof (struct ip6_hdr)));
313 pkt->udp_dns.udp_hdr.crc = calculate_checksum_end (sum);
314
315 pkt->ip6_hdr.version = 6;
316 pkt->ip6_hdr.paylgth = net_len - sizeof (struct ip6_hdr);
317 pkt->ip6_hdr.nxthdr = IPPROTO_UDP;
318 pkt->ip6_hdr.hoplmt = 0xff;
319
320 memcpy (&pkt->udp_dns.data, ans->pkt.data, data_len);
321 (void) GNUNET_HELPER_send (helper_handle,
322 &pkt->shdr,
323 GNUNET_YES,
324 &helper_write, NULL);
325 }
326 else if (ans->pkt.addrlen == 4)
327 {
328 size_t net_len =
329 sizeof (struct ip_hdr) + sizeof (struct udp_dns) + data_len;
330 pkt_len =
331 sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) +
332 net_len;
333
334 struct ip_udp_dns *pkt = alloca (pkt_len);
335
336 GNUNET_assert (pkt != NULL);
337 memset (pkt, 0, pkt_len);
338
339 /* set the gnunet-header */
340 pkt->shdr.size = htons (pkt_len);
341 pkt->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
342
343 /* set the tun-header (no flags and ethertype of IPv4) */
344 pkt->tun.flags = 0;
345 pkt->tun.type = htons (0x0800);
346
347 /* set the ip-header */
348 pkt->ip_hdr.version = 4;
349 pkt->ip_hdr.hdr_lngth = 5;
350 pkt->ip_hdr.diff_serv = 0;
351 pkt->ip_hdr.tot_lngth = htons (net_len);
352 pkt->ip_hdr.ident = 0;
353 pkt->ip_hdr.flags = 0;
354 pkt->ip_hdr.frag_off = 0;
355 pkt->ip_hdr.ttl = 255;
356 pkt->ip_hdr.proto = IPPROTO_UDP;
357 pkt->ip_hdr.chks = 0; /* Will be calculated later */
358
359 memcpy (&pkt->ip_hdr.sadr, ans->pkt.from, 4);
360 memcpy (&pkt->ip_hdr.dadr, ans->pkt.to, 4);
361
362 pkt->ip_hdr.chks =
363 calculate_ip_checksum ((uint16_t *) & pkt->ip_hdr, 5 * 4);
364
365 /* set the udp-header */
366 pkt->udp_dns.udp_hdr.spt = htons (53);
367 pkt->udp_dns.udp_hdr.dpt = ans->pkt.dst_port;
368 pkt->udp_dns.udp_hdr.len = htons (net_len - sizeof (struct ip_hdr));
369 pkt->udp_dns.udp_hdr.crc = 0; /* Optional for IPv4 */
370
371 memcpy (&pkt->udp_dns.data, ans->pkt.data, data_len);
372 (void) GNUNET_HELPER_send (helper_handle,
373 &pkt->shdr,
374 GNUNET_YES,
375 &helper_write, NULL);
376
377 }
378 else
379 {
380 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Wrong addrlen = %d\n",
381 ans->pkt.addrlen);
382 GNUNET_assert (0);
383 return; /* convince compiler that we're done here */
384 }
385
386 GNUNET_CONTAINER_DLL_remove (answer_proc_head, answer_proc_tail, ans);
387 GNUNET_free (ans);
388
389}
390
391/**
392 * Receive packets from the helper-process
393 */
394void
395message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
396 const struct GNUNET_MessageHeader *message)
397{
398 GNUNET_assert (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_HELPER);
399
400 struct tun_pkt *pkt_tun = (struct tun_pkt *) message;
401 GNUNET_HashCode *key;
402
403 /* ethertype is ipv6 */
404 if (ntohs (pkt_tun->tun.type) == 0x86dd)
405 {
406 struct ip6_pkt *pkt6 = (struct ip6_pkt *) message;
407
408 GNUNET_assert (pkt6->ip6_hdr.version == 6);
409 struct ip6_tcp *pkt6_tcp;
410 struct ip6_udp *pkt6_udp;
411 struct ip6_icmp *pkt6_icmp;
412
413 pkt6_udp = NULL; /* make compiler happy */
414 switch (pkt6->ip6_hdr.nxthdr)
415 {
416 case IPPROTO_UDP:
417 pkt6_udp = (struct ip6_udp *) pkt6;
418 /* Send dns-packets to the service-dns */
419 if (ntohs (pkt6_udp->udp_hdr.dpt) == 53)
420 {
421 /* 9 = 8 for the udp-header + 1 for the unsigned char data[1]; */
422 GNUNET_DNS_queue_request_v6 (dns_handle,
423 &pkt6->ip6_hdr.dadr,
424 &pkt6->ip6_hdr.sadr,
425 ntohs (pkt6_udp->udp_hdr.spt),
426 ntohs (pkt6_udp->udp_hdr.len) - 8,
427 (const void*) pkt6_udp->data);
428
429 break;
430 }
431 /* fall through */
432 case IPPROTO_TCP:
433 pkt6_tcp = (struct ip6_tcp *) pkt6;
434
435 if ((key = address6_mapping_exists (&pkt6->ip6_hdr.dadr)) != NULL)
436 {
437 struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
438
439 GNUNET_assert (me != NULL);
440 GNUNET_free (key);
441
442 size_t size =
443 sizeof (struct GNUNET_MESH_Tunnel *) +
444 sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) +
445 ntohs (pkt6->ip6_hdr.paylgth);
446
447 struct GNUNET_MESH_Tunnel **cls = GNUNET_malloc (size);
448 struct GNUNET_MessageHeader *hdr =
449 (struct GNUNET_MessageHeader *) (cls + 1);
450 GNUNET_HashCode *hc = (GNUNET_HashCode *) (hdr + 1);
451
452 hdr->size =
453 htons (sizeof (struct GNUNET_MessageHeader) +
454 sizeof (GNUNET_HashCode) + ntohs (pkt6->ip6_hdr.paylgth));
455
456 GNUNET_MESH_ApplicationType app_type = 0; /* fix compiler uninitialized warning... */
457
458 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "me->addrlen is %d\n",
459 me->addrlen);
460 if (me->addrlen == 0)
461 {
462 /* This is a mapping to a gnunet-service */
463 memcpy (hc, &me->desc.service_descriptor, sizeof (GNUNET_HashCode));
464
465 if (IPPROTO_UDP == pkt6->ip6_hdr.nxthdr &&
466 (me->desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_UDP)) &&
467 (port_in_ports (me->desc.ports, pkt6_udp->udp_hdr.dpt) ||
468 testBit (me->additional_ports, ntohs (pkt6_udp->udp_hdr.dpt))))
469 {
470 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP);
471
472 memcpy (hc + 1, &pkt6_udp->udp_hdr, ntohs (pkt6_udp->udp_hdr.len));
473
474 }
475 else if (IPPROTO_TCP == pkt6->ip6_hdr.nxthdr &&
476 (me->desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_TCP))
477 && (port_in_ports (me->desc.ports, pkt6_tcp->tcp_hdr.dpt)))
478 {
479 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP);
480
481 memcpy (hc + 1, &pkt6_tcp->tcp_hdr, ntohs (pkt6->ip6_hdr.paylgth));
482
483 }
484 else
485 {
486 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pip: %d\n",
487 port_in_ports (me->desc.ports, pkt6_tcp->tcp_hdr.dpt));
488 GNUNET_assert (0);
489 }
490 if (me->tunnel == NULL && NULL != cls)
491 {
492 *cls =
493 GNUNET_MESH_tunnel_create (mesh_handle,
494 initialize_tunnel_state (16, NULL),
495 &send_pkt_to_peer, NULL, cls);
496
497 GNUNET_MESH_peer_request_connect_add (*cls,
498 (struct GNUNET_PeerIdentity *)
499 &me->desc.peer);
500 me->tunnel = *cls;
501 }
502 else if (NULL != cls)
503 {
504 *cls = me->tunnel;
505 send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL);
506 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
507 "Queued to send IPv6 to peer %x, type %d\n",
508 *((unsigned int *) &me->desc.peer), ntohs (hdr->type));
509 }
510 }
511 else
512 {
513 /* This is a mapping to a "real" address */
514 struct remote_addr *s = (struct remote_addr *) hc;
515
516 s->addrlen = me->addrlen;
517 memcpy (s->addr, me->addr, me->addrlen);
518 s->proto = pkt6->ip6_hdr.nxthdr;
519 if (s->proto == IPPROTO_UDP)
520 {
521 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP);
522 memcpy (hc + 1, &pkt6_udp->udp_hdr, ntohs (pkt6_udp->udp_hdr.len));
523 app_type = GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY;
524 if (NULL != udp_tunnel)
525 me->tunnel = udp_tunnel;
526 }
527 else if (s->proto == IPPROTO_TCP)
528 {
529 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP);
530 memcpy (hc + 1, &pkt6_tcp->tcp_hdr, ntohs (pkt6->ip6_hdr.paylgth));
531 app_type = GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY;
532 if (NULL != tcp_tunnel)
533 me->tunnel = tcp_tunnel;
534 }
535 else
536 {
537 GNUNET_assert (0);
538 }
539 if (me->tunnel == NULL && NULL != cls)
540 {
541 *cls =
542 GNUNET_MESH_tunnel_create (mesh_handle,
543 initialize_tunnel_state (16, NULL),
544 &send_pkt_to_peer, NULL, cls);
545
546 GNUNET_MESH_peer_request_connect_by_type (*cls, app_type);
547 me->tunnel = *cls;
548 if (GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY == app_type)
549 udp_tunnel = *cls;
550 else if (GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY == app_type)
551 tcp_tunnel = *cls;
552 }
553 else if (NULL != cls)
554 {
555 *cls = me->tunnel;
556 send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL);
557 }
558 }
559 }
560 else
561 {
562 char pbuf[INET6_ADDRSTRLEN];
563 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
564 "Packet to %s, which has no mapping\n",
565 inet_ntop (AF_INET6,
566 &pkt6->ip6_hdr.dadr,
567 pbuf,
568 sizeof (pbuf)));
569 }
570 break;
571 case 0x3a:
572 /* ICMPv6 */
573 pkt6_icmp = (struct ip6_icmp *) pkt6;
574 /* If this packet is an icmp-echo-request and a mapping exists, answer */
575 if (pkt6_icmp->icmp_hdr.type == 0x80 &&
576 (key = address6_mapping_exists (&pkt6->ip6_hdr.dadr)) != NULL)
577 {
578 GNUNET_free (key);
579 pkt6_icmp = GNUNET_malloc (ntohs (pkt6->shdr.size));
580 memcpy (pkt6_icmp, pkt6, ntohs (pkt6->shdr.size));
581 GNUNET_SCHEDULER_add_now (&send_icmp6_response, pkt6_icmp);
582 }
583 break;
584 }
585 }
586 /* ethertype is ipv4 */
587 else if (ntohs (pkt_tun->tun.type) == 0x0800)
588 {
589 struct ip_pkt *pkt = (struct ip_pkt *) message;
590 struct ip_udp *udp = (struct ip_udp *) message;
591 struct ip_tcp *pkt_tcp;
592 struct ip_udp *pkt_udp;
593 struct ip_icmp *pkt_icmp;
594
595 GNUNET_assert (pkt->ip_hdr.version == 4);
596
597 /* Send dns-packets to the service-dns */
598 if (pkt->ip_hdr.proto == IPPROTO_UDP && ntohs (udp->udp_hdr.dpt) == 53)
599 {
600 GNUNET_DNS_queue_request_v4 (dns_handle,
601 &pkt->ip_hdr.dadr,
602 &pkt->ip_hdr.sadr,
603 ntohs (udp->udp_hdr.spt),
604 ntohs (udp->udp_hdr.len) - 8,
605 (const void*) udp->data);
606 }
607 else
608 {
609 uint32_t dadr = pkt->ip_hdr.dadr.s_addr;
610 unsigned char *c = (unsigned char *) &dadr;
611
612 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Packet to %d.%d.%d.%d, proto %x\n",
613 c[0], c[1], c[2], c[3], pkt->ip_hdr.proto);
614 switch (pkt->ip_hdr.proto)
615 {
616 case IPPROTO_TCP:
617 case IPPROTO_UDP:
618 pkt_tcp = (struct ip_tcp *) pkt;
619 pkt_udp = (struct ip_udp *) pkt;
620
621 if ((key = address4_mapping_exists (dadr)) != NULL)
622 {
623 struct map_entry *me =
624 GNUNET_CONTAINER_multihashmap_get (hashmap, key);
625 GNUNET_assert (me != NULL);
626 GNUNET_free (key);
627
628 size_t size =
629 sizeof (struct GNUNET_MESH_Tunnel *) +
630 sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) +
631 ntohs (pkt->ip_hdr.tot_lngth) - 4 * pkt->ip_hdr.hdr_lngth;
632
633 struct GNUNET_MESH_Tunnel **cls = GNUNET_malloc (size);
634 struct GNUNET_MessageHeader *hdr =
635 (struct GNUNET_MessageHeader *) (cls + 1);
636 GNUNET_HashCode *hc = (GNUNET_HashCode *) (hdr + 1);
637
638 hdr->size =
639 htons (sizeof (struct GNUNET_MessageHeader) +
640 sizeof (GNUNET_HashCode) + ntohs (pkt->ip_hdr.tot_lngth) -
641 4 * pkt->ip_hdr.hdr_lngth);
642
643 GNUNET_MESH_ApplicationType app_type = 0; /* make compiler happy */
644
645 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "me->addrlen is %d\n",
646 me->addrlen);
647 if (me->addrlen == 0)
648 {
649 /* This is a mapping to a gnunet-service */
650 memcpy (hc, &me->desc.service_descriptor, sizeof (GNUNET_HashCode));
651
652 if ((IPPROTO_UDP == pkt->ip_hdr.proto) &&
653 (me->desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_UDP)) &&
654 (port_in_ports (me->desc.ports, pkt_udp->udp_hdr.dpt) ||
655 testBit (me->additional_ports, ntohs (pkt_udp->udp_hdr.dpt))))
656 {
657 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP);
658
659 memcpy (hc + 1, &pkt_udp->udp_hdr, ntohs (pkt_udp->udp_hdr.len));
660
661 }
662 else if ((IPPROTO_TCP == pkt->ip_hdr.proto) &&
663 (me->
664 desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_TCP))
665 && (port_in_ports (me->desc.ports, pkt_tcp->tcp_hdr.dpt)))
666 {
667 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP);
668
669 memcpy (hc + 1, &pkt_tcp->tcp_hdr,
670 ntohs (pkt->ip_hdr.tot_lngth) -
671 4 * pkt->ip_hdr.hdr_lngth);
672
673 }
674 if (me->tunnel == NULL && NULL != cls)
675 {
676 *cls =
677 GNUNET_MESH_tunnel_create (mesh_handle,
678 initialize_tunnel_state (4, NULL),
679 send_pkt_to_peer, NULL, cls);
680 GNUNET_MESH_peer_request_connect_add (*cls,
681 (struct GNUNET_PeerIdentity
682 *) &me->desc.peer);
683 me->tunnel = *cls;
684 }
685 else if (NULL != cls)
686 {
687 *cls = me->tunnel;
688 send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL);
689 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
690 "Queued to send IPv4 to peer %x, type %d\n",
691 *((unsigned int *) &me->desc.peer),
692 ntohs (hdr->type));
693 }
694 }
695 else
696 {
697 /* This is a mapping to a "real" address */
698 struct remote_addr *s = (struct remote_addr *) hc;
699
700 s->addrlen = me->addrlen;
701 memcpy (s->addr, me->addr, me->addrlen);
702 s->proto = pkt->ip_hdr.proto;
703 if (s->proto == IPPROTO_UDP)
704 {
705 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP);
706 memcpy (hc + 1, &pkt_udp->udp_hdr, ntohs (pkt_udp->udp_hdr.len));
707 app_type = GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY;
708 }
709 else if (s->proto == IPPROTO_TCP)
710 {
711 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP);
712 memcpy (hc + 1, &pkt_tcp->tcp_hdr,
713 ntohs (pkt->ip_hdr.tot_lngth) -
714 4 * pkt->ip_hdr.hdr_lngth);
715 app_type = GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY;
716 }
717 else
718 GNUNET_assert (0);
719 if (me->tunnel == NULL && NULL != cls)
720 {
721 *cls =
722 GNUNET_MESH_tunnel_create (mesh_handle,
723 initialize_tunnel_state (4, NULL),
724 send_pkt_to_peer, NULL, cls);
725
726 GNUNET_MESH_peer_request_connect_by_type (*cls, app_type);
727 me->tunnel = *cls;
728 }
729 else if (NULL != cls)
730 {
731 *cls = me->tunnel;
732 send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL);
733 }
734 }
735 }
736 else
737 {
738 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
739 "Packet to %x which has no mapping\n", dadr);
740 }
741 break;
742 case 0x01:
743 /* ICMP */
744 pkt_icmp = (struct ip_icmp *) pkt;
745 if (pkt_icmp->icmp_hdr.type == 0x8 &&
746 (key = address4_mapping_exists (dadr)) != NULL)
747 {
748 GNUNET_free (key);
749 pkt_icmp = GNUNET_malloc (ntohs (pkt->shdr.size));
750 memcpy (pkt_icmp, pkt, ntohs (pkt->shdr.size));
751 GNUNET_SCHEDULER_add_now (&send_icmp4_response, pkt_icmp);
752 }
753 break;
754 }
755 }
756 }
757}
758
759
760
213static void 761static void
214collect_mappings (void *cls GNUNET_UNUSED, 762collect_mappings (void *cls GNUNET_UNUSED,
215 const struct GNUNET_SCHEDULER_TaskContext *tc) 763 const struct GNUNET_SCHEDULER_TaskContext *tc)
@@ -269,8 +817,10 @@ send_icmp4_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
269 memcpy (response + 1, request + 1, 817 memcpy (response + 1, request + 1,
270 ntohs (request->shdr.size) - sizeof (struct ip_icmp)); 818 ntohs (request->shdr.size) - sizeof (struct ip_icmp));
271 819
272 write_to_helper (response, ntohs (response->shdr.size)); 820 (void) GNUNET_HELPER_send (helper_handle,
273 821 &response->shdr,
822 GNUNET_YES,
823 NULL, NULL);
274 GNUNET_free (request); 824 GNUNET_free (request);
275} 825}
276 826
@@ -310,8 +860,10 @@ send_icmp6_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
310 memcpy (response + 1, request + 1, 860 memcpy (response + 1, request + 1,
311 ntohs (request->shdr.size) - sizeof (struct ip6_icmp)); 861 ntohs (request->shdr.size) - sizeof (struct ip6_icmp));
312 862
313 write_to_helper (response, ntohs (response->shdr.size)); 863 (void) GNUNET_HELPER_send (helper_handle,
314 864 &response->shdr,
865 GNUNET_YES,
866 NULL, NULL);
315 GNUNET_free (request); 867 GNUNET_free (request);
316} 868}
317 869
@@ -824,9 +1376,6 @@ process_answer (void *cls,
824 GNUNET_CONTAINER_DLL_insert_after (answer_proc_head, answer_proc_tail, 1376 GNUNET_CONTAINER_DLL_insert_after (answer_proc_head, answer_proc_tail,
825 answer_proc_tail, list); 1377 answer_proc_tail, list);
826 1378
827 schedule_helper_write (GNUNET_TIME_UNIT_FOREVER_REL, NULL);
828
829 return;
830} 1379}
831 1380
832 1381
@@ -939,8 +1488,11 @@ receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
939 calculate_checksum_update (sum, (uint16_t *) & pkt6->udp_hdr, 1488 calculate_checksum_update (sum, (uint16_t *) & pkt6->udp_hdr,
940 ntohs (pkt->len)); 1489 ntohs (pkt->len));
941 pkt6->udp_hdr.crc = calculate_checksum_end (sum); 1490 pkt6->udp_hdr.crc = calculate_checksum_end (sum);
942 1491
943 write_to_helper (pkt6, size); 1492 (void) GNUNET_HELPER_send (helper_handle,
1493 &pkt6->shdr,
1494 GNUNET_YES,
1495 NULL, NULL);
944 } 1496 }
945 else 1497 else
946 { 1498 {
@@ -1011,7 +1563,10 @@ receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1011 pkt4->ip_hdr.chks = 1563 pkt4->ip_hdr.chks =
1012 calculate_ip_checksum ((uint16_t *) & pkt4->ip_hdr, 5 * 4); 1564 calculate_ip_checksum ((uint16_t *) & pkt4->ip_hdr, 5 * 4);
1013 1565
1014 write_to_helper (pkt4, size); 1566 (void) GNUNET_HELPER_send (helper_handle,
1567 &pkt4->shdr,
1568 GNUNET_YES,
1569 NULL, NULL);
1015 } 1570 }
1016 1571
1017 return GNUNET_OK; 1572 return GNUNET_OK;
@@ -1113,7 +1668,10 @@ receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1113 ntohs (pkt6->ip6_hdr.paylgth)); 1668 ntohs (pkt6->ip6_hdr.paylgth));
1114 pkt6->tcp_hdr.crc = calculate_checksum_end (sum); 1669 pkt6->tcp_hdr.crc = calculate_checksum_end (sum);
1115 1670
1116 write_to_helper (pkt6, size); 1671 (void) GNUNET_HELPER_send (helper_handle,
1672 &pkt6->shdr,
1673 GNUNET_YES,
1674 NULL, NULL);
1117 } 1675 }
1118 else 1676 else
1119 { 1677 {
@@ -1194,7 +1752,11 @@ receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1194 pkt4->ip_hdr.chks = 1752 pkt4->ip_hdr.chks =
1195 calculate_ip_checksum ((uint16_t *) & pkt4->ip_hdr, 5 * 4); 1753 calculate_ip_checksum ((uint16_t *) & pkt4->ip_hdr, 5 * 4);
1196 1754
1197 write_to_helper (pkt4, size); 1755 (void) GNUNET_HELPER_send (helper_handle,
1756 &pkt4->shdr,
1757 GNUNET_YES,
1758 NULL, NULL);
1759
1198 } 1760 }
1199 1761
1200 return GNUNET_OK; 1762 return GNUNET_OK;
@@ -1237,10 +1799,14 @@ run (void *cls, char *const *args GNUNET_UNUSED,
1237 {receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP_BACK, 0}, 1799 {receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP_BACK, 0},
1238 {NULL, 0, 0} 1800 {NULL, 0, 0}
1239 }; 1801 };
1240
1241 static const GNUNET_MESH_ApplicationType types[] = { 1802 static const GNUNET_MESH_ApplicationType types[] = {
1242 GNUNET_APPLICATION_TYPE_END 1803 GNUNET_APPLICATION_TYPE_END
1243 }; 1804 };
1805 char *ifname;
1806 char *ipv6addr;
1807 char *ipv6prefix;
1808 char *ipv4addr;
1809 char *ipv4mask;
1244 1810
1245 mesh_handle = 1811 mesh_handle =
1246 GNUNET_MESH_connect (cfg_, 42, NULL, new_tunnel, cleaner, handlers, 1812 GNUNET_MESH_connect (cfg_, 42, NULL, new_tunnel, cleaner, handlers,
@@ -1254,8 +1820,58 @@ run (void *cls, char *const *args GNUNET_UNUSED,
1254 dns_handle = GNUNET_DNS_connect (cfg, 1820 dns_handle = GNUNET_DNS_connect (cfg,
1255 &process_answer, 1821 &process_answer,
1256 NULL); 1822 NULL);
1257 shs_task = 1823 if (GNUNET_SYSERR ==
1258 GNUNET_SCHEDULER_add_after (conn_task, start_helper_and_schedule, NULL); 1824 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IFNAME", &ifname))
1825 {
1826 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1827 "No entry 'IFNAME' in configuration!\n");
1828 exit (1);
1829 }
1830
1831 if (GNUNET_SYSERR ==
1832 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR", &ipv6addr))
1833 {
1834 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1835 "No entry 'IPV6ADDR' in configuration!\n");
1836 exit (1);
1837 }
1838
1839 if (GNUNET_SYSERR ==
1840 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6PREFIX",
1841 &ipv6prefix))
1842 {
1843 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1844 "No entry 'IPV6PREFIX' in configuration!\n");
1845 exit (1);
1846 }
1847
1848 if (GNUNET_SYSERR ==
1849 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR", &ipv4addr))
1850 {
1851 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1852 "No entry 'IPV4ADDR' in configuration!\n");
1853 exit (1);
1854 }
1855
1856 if (GNUNET_SYSERR ==
1857 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK", &ipv4mask))
1858 {
1859 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1860 "No entry 'IPV4MASK' in configuration!\n");
1861 exit (1);
1862 }
1863
1864 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
1865 vpn_argv[1] = ifname;
1866 vpn_argv[2] = ipv6addr;
1867 vpn_argv[3] = ipv6prefix;
1868 vpn_argv[4] = ipv4addr;
1869 vpn_argv[5] = ipv4mask;
1870 vpn_argv[6] = NULL;
1871
1872 helper_handle = GNUNET_HELPER_start ("gnunet-helper-vpn", vpn_argv,
1873 &message_token, NULL);
1874 GNUNET_DNS_restart_hijack (dns_handle);
1259 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls); 1875 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
1260} 1876}
1261 1877
diff --git a/src/vpn/gnunet-helper-vpn-api.c b/src/vpn/gnunet-helper-vpn-api.c
index 379e75765..d2b5673d0 100644
--- a/src/vpn/gnunet-helper-vpn-api.c
+++ b/src/vpn/gnunet-helper-vpn-api.c
@@ -32,71 +32,6 @@
32 32
33#include "gnunet-helper-vpn-api.h" 33#include "gnunet-helper-vpn-api.h"
34 34
35static void
36stop_helper (struct GNUNET_VPN_HELPER_Handle *handle)
37{
38 if (NULL == handle->helper_proc)
39 return;
40 GNUNET_OS_process_kill (handle->helper_proc, SIGKILL);
41 GNUNET_OS_process_wait (handle->helper_proc);
42 GNUNET_OS_process_close (handle->helper_proc);
43 handle->helper_proc = NULL;
44
45 GNUNET_DISK_pipe_close (handle->helper_in);
46 GNUNET_DISK_pipe_close (handle->helper_out);
47
48 GNUNET_SERVER_mst_destroy (handle->mst);
49}
50
51extern GNUNET_SCHEDULER_TaskIdentifier shs_task;
52
53/**
54 * Read from the helper-process
55 */
56static void
57helper_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tsdkctx)
58{
59 struct GNUNET_VPN_HELPER_Handle *handle = cls;
60
61 /* no message can be bigger then 64k */
62 char buf[65535];
63
64 if (tsdkctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)
65 return;
66
67 int t = GNUNET_DISK_file_read (handle->fh_from_helper, &buf, 65535);
68
69 /* On read-error, restart the helper */
70 if (t <= 0)
71 {
72 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
73 "Read error for header from vpn-helper: %m\n");
74 stop_helper (handle);
75
76 /* Restart the helper */
77 shs_task =
78 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
79 handle->restart_task, handle);
80 return;
81 }
82
83 if (GNUNET_SYSERR ==
84 GNUNET_SERVER_mst_receive (handle->mst, handle->client, buf, t, 0, 0))
85 {
86 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "SYSERR from mst\n");
87 stop_helper (handle);
88
89 /* Restart the helper */
90 shs_task =
91 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
92 handle->restart_task, handle);
93 return;
94
95 }
96
97 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
98 handle->fh_from_helper, &helper_read, handle);
99}
100 35
101void 36void
102cleanup_helper (struct GNUNET_VPN_HELPER_Handle *handle) 37cleanup_helper (struct GNUNET_VPN_HELPER_Handle *handle)
@@ -111,37 +46,4 @@ start_helper (const char *ifname, const char *ipv6addr, const char *ipv6prefix,
111 const char *process_name, GNUNET_SCHEDULER_Task restart_task, 46 const char *process_name, GNUNET_SCHEDULER_Task restart_task,
112 GNUNET_SERVER_MessageTokenizerCallback cb, void *cb_cls) 47 GNUNET_SERVER_MessageTokenizerCallback cb, void *cb_cls)
113{ 48{
114 struct GNUNET_VPN_HELPER_Handle *handle =
115 GNUNET_malloc (sizeof (struct GNUNET_VPN_HELPER_Handle));
116
117 handle->helper_in = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO);
118 handle->helper_out = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES);
119
120 handle->restart_task = restart_task;
121 49
122 if (handle->helper_in == NULL || handle->helper_out == NULL)
123 {
124 GNUNET_free (handle);
125 return NULL;
126 }
127
128 handle->helper_proc =
129 GNUNET_OS_start_process (handle->helper_in, handle->helper_out,
130 "gnunet-helper-vpn", process_name, ifname,
131 ipv6addr, ipv6prefix, ipv4addr, ipv4mask, NULL);
132
133 handle->fh_from_helper =
134 GNUNET_DISK_pipe_handle (handle->helper_out, GNUNET_DISK_PIPE_END_READ);
135 handle->fh_to_helper =
136 GNUNET_DISK_pipe_handle (handle->helper_in, GNUNET_DISK_PIPE_END_WRITE);
137
138 GNUNET_DISK_pipe_close_end (handle->helper_out, GNUNET_DISK_PIPE_END_WRITE);
139 GNUNET_DISK_pipe_close_end (handle->helper_in, GNUNET_DISK_PIPE_END_READ);
140
141 handle->mst = GNUNET_SERVER_mst_create (cb, cb_cls);
142
143 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
144 handle->fh_from_helper, &helper_read, handle);
145
146 return handle;
147}
diff --git a/src/vpn/gnunet-helper-vpn-api.h b/src/vpn/gnunet-helper-vpn-api.h
deleted file mode 100644
index 964beb23c..000000000
--- a/src/vpn/gnunet-helper-vpn-api.h
+++ /dev/null
@@ -1,110 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010 Christian Grothoff
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file vpn/gnunet-helper-vpn-api.h
23 * @brief exposes the API (the convenience-functions) of dealing with the
24 * helper-vpn
25 * @author Philipp Toelke
26 */
27#ifndef GNUNET_HELPER_VPN_API_H
28#define GNUNET_HELPER_VPN_API_H
29
30/**
31 * The handle to a helper.
32 * sometimes a few entries may be made opaque.
33 */
34struct GNUNET_VPN_HELPER_Handle
35{
36/**
37 * PipeHandle to receive data from the helper
38 */
39 struct GNUNET_DISK_PipeHandle *helper_in;
40
41/**
42 * PipeHandle to send data to the helper
43 */
44 struct GNUNET_DISK_PipeHandle *helper_out;
45
46/**
47 * FileHandle to receive data from the helper
48 */
49 const struct GNUNET_DISK_FileHandle *fh_from_helper;
50
51/**
52 * FileHandle to send data to the helper
53 */
54 const struct GNUNET_DISK_FileHandle *fh_to_helper;
55
56 /**
57 * The process id of the helper
58 */
59 struct GNUNET_OS_Process *helper_proc;
60
61 /**
62 * The Message-Tokenizer that tokenizes the messages comming from the helper
63 */
64 struct GNUNET_SERVER_MessageStreamTokenizer *mst;
65
66 /**
67 * The client-identifier passed to the mst-callback
68 */
69 void *client;
70
71 /**
72 * The name of the interface
73 */
74 char *ifname;
75
76 /**
77 * The task called when the helper dies.
78 * Will be called with the handle as cls
79 */
80 GNUNET_SCHEDULER_Task restart_task;
81};
82
83/**
84 * @brief Starts a helper and begins reading from it
85 *
86 * @param ifname The name of the new interface
87 * @param ipv6addr The IPv6 address of the new interface
88 * @param ipv6prefix The IPv6 prefix length of the new IP
89 * @param ipv4addr The IPv4 address of the new interface
90 * @param ipv4mask The associated netmask
91 * @param process_name How the helper should appear in process-listings
92 * @param restart_task The task called when the helper dies. Will be called with the handle as cls
93 * @param cb A callback for messages from the helper
94 * @param cb_cls Closure for the callback
95 *
96 * @return A pointer to the new Handle, NULL on error
97 */
98struct GNUNET_VPN_HELPER_Handle *
99start_helper (const char *ifname, const char *ipv6addr, const char *ipv6prefix,
100 const char *ipv4addr, const char *ipv4mask,
101 const char *process_name, GNUNET_SCHEDULER_Task restart_task,
102 GNUNET_SERVER_MessageTokenizerCallback cb, void *cb_cls);
103
104/**
105 * @brief Kills the helper, closes the pipe and free()s the handle
106 */
107void
108cleanup_helper (struct GNUNET_VPN_HELPER_Handle *);
109
110#endif /* end of include guard: GNUNET_HELPER_VPN_API_H */