aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/exit/gnunet-daemon-exit.c2
-rw-r--r--src/include/gnunet_applications.h10
-rw-r--r--src/util/server_nc.c3
-rw-r--r--src/vpn/gnunet-service-vpn.c356
4 files changed, 352 insertions, 19 deletions
diff --git a/src/exit/gnunet-daemon-exit.c b/src/exit/gnunet-daemon-exit.c
index 9090ca32c..4ce0f634f 100644
--- a/src/exit/gnunet-daemon-exit.c
+++ b/src/exit/gnunet-daemon-exit.c
@@ -1916,6 +1916,8 @@ run (void *cls, char *const *args GNUNET_UNUSED,
1916 1916
1917 app_idx = 0; 1917 app_idx = 0;
1918 handler_idx = 2; 1918 handler_idx = 2;
1919 // FIXME: new 'vpn' has other apptypes (IPv4/IPv6, no longer TCP vs. UDP)!
1920 // The new 'exit' should reflect that!
1919 udp = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_UDP"); 1921 udp = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_UDP");
1920 tcp = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_TCP"); 1922 tcp = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_TCP");
1921 if (GNUNET_YES == udp) 1923 if (GNUNET_YES == udp)
diff --git a/src/include/gnunet_applications.h b/src/include/gnunet_applications.h
index d11d4b0f2..d9df78d33 100644
--- a/src/include/gnunet_applications.h
+++ b/src/include/gnunet_applications.h
@@ -75,6 +75,16 @@ extern "C"
75 */ 75 */
76#define GNUNET_APPLICATION_TYPE_GNUNET_SEARCH 7 76#define GNUNET_APPLICATION_TYPE_GNUNET_SEARCH 7
77 77
78/**
79 * Internet IPv4 gateway (any TCP/UDP/ICMP).
80 */
81#define GNUNET_APPLICATION_TYPE_IPV4_GATEWAY 16
82
83/**
84 * Internet IPv6 gateway (any TCP/UDP/ICMP).
85 */
86#define GNUNET_APPLICATION_TYPE_IPV6_GATEWAY 17
87
78 88
79#if 0 /* keep Emacsens' auto-indent happy */ 89#if 0 /* keep Emacsens' auto-indent happy */
80{ 90{
diff --git a/src/util/server_nc.c b/src/util/server_nc.c
index a36fa0c50..08ffd4b0c 100644
--- a/src/util/server_nc.c
+++ b/src/util/server_nc.c
@@ -262,6 +262,9 @@ GNUNET_SERVER_notification_context_add (struct GNUNET_SERVER_NotificationContext
262{ 262{
263 struct ClientList *cl; 263 struct ClientList *cl;
264 264
265 for (cl = nc->clients; NULL != cl; cl = cl->next)
266 if (cl->client == client)
267 return; /* already present */
265 cl = GNUNET_malloc (sizeof (struct ClientList)); 268 cl = GNUNET_malloc (sizeof (struct ClientList));
266 cl->next = nc->clients; 269 cl->next = nc->clients;
267 cl->nc = nc; 270 cl->nc = nc;
diff --git a/src/vpn/gnunet-service-vpn.c b/src/vpn/gnunet-service-vpn.c
index 27490db50..a1848728b 100644
--- a/src/vpn/gnunet-service-vpn.c
+++ b/src/vpn/gnunet-service-vpn.c
@@ -27,13 +27,15 @@
27 * @author Christian Grothoff 27 * @author Christian Grothoff
28 * 28 *
29 * TODO: 29 * TODO:
30 * - create tunnels
31 * - implement service message handlers 30 * - implement service message handlers
32 * - define mesh message formats between VPN and EXIT! 31 * - define mesh message formats between VPN and EXIT!
33 * - build mesh messages 32 * - build mesh messages
34 * - parse mesh replies 33 * - parse mesh replies
35 * - build IP messages from mesh replies 34 * - build IP messages from mesh replies
35 * - create secondary mesh tunnels if needed
36 * - fully implement shutdown code 36 * - fully implement shutdown code
37 * - better message queue management (bounded state, drop oldest/RED?)
38 * - imrpove support for deciding which tunnels to keep and which ones to destroy
37 * - add back ICMP support (especially needed for IPv6) 39 * - add back ICMP support (especially needed for IPv6)
38 */ 40 */
39#include "platform.h" 41#include "platform.h"
@@ -144,7 +146,8 @@ struct TunnelState
144 struct GNUNET_MESH_TransmitHandle *th; 146 struct GNUNET_MESH_TransmitHandle *th;
145 147
146 /** 148 /**
147 * Entry for this entry in the tunnel_heap. 149 * Entry for this entry in the tunnel_heap, NULL as long as this
150 * tunnel state is not fully bound.
148 */ 151 */
149 struct GNUNET_CONTAINER_HeapNode *heap_node; 152 struct GNUNET_CONTAINER_HeapNode *heap_node;
150 153
@@ -159,6 +162,17 @@ struct TunnelState
159 struct TunnelMessageQueueEntry *tail; 162 struct TunnelMessageQueueEntry *tail;
160 163
161 /** 164 /**
165 * Client that needs to be notified about the tunnel being
166 * up as soon as a peer is connected; NULL for none.
167 */
168 struct GNUNET_SERVER_Client *client;
169
170 /**
171 * ID of the client request that caused us to setup this entry.
172 */
173 uint64_t request_id;
174
175 /**
162 * Destination to which this tunnel leads. Note that 176 * Destination to which this tunnel leads. Note that
163 * this struct is NOT in the destination_map (but a 177 * this struct is NOT in the destination_map (but a
164 * local copy) and that the 'heap_node' should always 178 * local copy) and that the 'heap_node' should always
@@ -173,7 +187,12 @@ struct TunnelState
173 int is_service; 187 int is_service;
174 188
175 /** 189 /**
176 * IP address of the source on our end. 190 * Addess family used for this tunnel on the local TUN interface.
191 */
192 int af;
193
194 /**
195 * IP address of the source on our end, initially uninitialized.
177 */ 196 */
178 union 197 union
179 { 198 {
@@ -190,7 +209,8 @@ struct TunnelState
190 } source_ip; 209 } source_ip;
191 210
192 /** 211 /**
193 * Destination IP address used by the source on our end. 212 * Destination IP address used by the source on our end (this is the IP
213 * that we pick freely within the VPN's tunnel IP range).
194 */ 214 */
195 union 215 union
196 { 216 {
@@ -207,12 +227,12 @@ struct TunnelState
207 } destination_ip; 227 } destination_ip;
208 228
209 /** 229 /**
210 * Source port used by the sender on our end. 230 * Source port used by the sender on our end; 0 for uninitialized.
211 */ 231 */
212 uint16_t source_port; 232 uint16_t source_port;
213 233
214 /** 234 /**
215 * Destination port used by the sender on our end. 235 * Destination port used by the sender on our end; 0 for uninitialized.
216 */ 236 */
217 uint16_t destination_port; 237 uint16_t destination_port;
218 238
@@ -262,6 +282,11 @@ static struct GNUNET_HELPER_Handle *helper_handle;
262static char *vpn_argv[7]; 282static char *vpn_argv[7];
263 283
264/** 284/**
285 * Notification context for sending replies to clients.
286 */
287static struct GNUNET_SERVER_NotificationContext *nc;
288
289/**
265 * If there are more than this number of address-mappings, old ones 290 * If there are more than this number of address-mappings, old ones
266 * will be removed 291 * will be removed
267 */ 292 */
@@ -1066,6 +1091,131 @@ receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1066 1091
1067 1092
1068/** 1093/**
1094 * Allocate an IPv4 address from the range of the tunnel
1095 * for a new redirection.
1096 *
1097 * @param v4 where to store the address
1098 * @return GNUNET_OK on success,
1099 * GNUNET_SYSERR on error
1100 */
1101static int
1102allocate_v4_address (struct in_addr *v4)
1103{
1104 // FIXME: implement!
1105 return GNUNET_SYSERR;
1106}
1107
1108
1109/**
1110 * Allocate an IPv6 address from the range of the tunnel
1111 * for a new redirection.
1112 *
1113 * @param v6 where to store the address
1114 * @return GNUNET_OK on success,
1115 * GNUNET_SYSERR on error
1116 */
1117static int
1118allocate_v6_address (struct in6_addr *v4)
1119{
1120 // FIXME: implement!
1121 return GNUNET_SYSERR;
1122}
1123
1124
1125/**
1126 * Notify the client about the result of its request.
1127 *
1128 * @param client client to notify
1129 * @param request_id original request ID to include in response
1130 * @param result_af resulting address family
1131 * @param addr resulting IP address
1132 */
1133static void
1134send_client_reply (struct GNUNET_SERVER_Client *client,
1135 uint64_t request_id,
1136 int result_af,
1137 const void *addr)
1138{
1139 char buf[sizeof (struct RedirectToIpResponseMessage) + sizeof (struct in6_addr)];
1140 struct RedirectToIpResponseMessage *res;
1141 size_t rlen;
1142
1143 switch (result_af)
1144 {
1145 case AF_INET:
1146 rlen = sizeof (struct in_addr);
1147 break;
1148 case AF_INET6:
1149 rlen = sizeof (struct in6_addr);
1150 break;
1151 case AF_UNSPEC:
1152 rlen = 0;
1153 break;
1154 default:
1155 GNUNET_assert (0);
1156 return;
1157 }
1158 res = (struct RedirectToIpResponseMessage *) buf;
1159 res->header.size = htons (sizeof (struct RedirectToIpResponseMessage) + rlen);
1160 res->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP);
1161 res->result_af = htonl (result_af);
1162 res->request_id = request_id;
1163 memcpy (&res[1], addr, rlen);
1164 GNUNET_SERVER_notification_context_add (nc, client);
1165 GNUNET_SERVER_notification_context_unicast (nc,
1166 client,
1167 &res->header,
1168 GNUNET_NO);
1169}
1170
1171
1172/**
1173 * Method called whenever a peer has disconnected from the tunnel.
1174 *
1175 * @param cls closure
1176 * @param peer peer identity the tunnel stopped working with
1177 */
1178static void
1179tunnel_peer_disconnect_handler (void *cls,
1180 const struct
1181 GNUNET_PeerIdentity * peer)
1182{
1183 /* FIXME: should we do anything here?
1184 - stop transmitting to the tunnel (start queueing?)
1185 - possibly destroy the tunnel entirely (unless service tunnel?)
1186 */
1187}
1188
1189
1190/**
1191 * Method called whenever a peer has connected to the tunnel. Notifies
1192 * the waiting client that the tunnel is now up.
1193 *
1194 * @param cls closure
1195 * @param peer peer identity the tunnel was created to, NULL on timeout
1196 * @param atsi performance data for the connection
1197 */
1198static void
1199tunnel_peer_connect_handler (void *cls,
1200 const struct GNUNET_PeerIdentity
1201 * peer,
1202 const struct
1203 GNUNET_ATS_Information * atsi)
1204{
1205 struct TunnelState *ts = cls;
1206
1207 if (NULL == ts->client)
1208 return; /* nothing to do */
1209 send_client_reply (ts->client,
1210 ts->request_id,
1211 ts->af,
1212 &ts->destination_ip);
1213 GNUNET_SERVER_client_drop (ts->client);
1214 ts->client = NULL;
1215}
1216
1217
1218/**
1069 * A client asks us to setup a redirection via some exit 1219 * A client asks us to setup a redirection via some exit
1070 * node to a particular IP. Setup the redirection and 1220 * node to a particular IP. Setup the redirection and
1071 * give the client the allocated IP. 1221 * give the client the allocated IP.
@@ -1078,7 +1228,153 @@ static void
1078service_redirect_to_ip (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client, 1228service_redirect_to_ip (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
1079 const struct GNUNET_MessageHeader *message) 1229 const struct GNUNET_MessageHeader *message)
1080{ 1230{
1081 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 1231 size_t mlen;
1232 size_t alen;
1233 const struct RedirectToIpRequestMessage *msg;
1234 int addr_af;
1235 int result_af;
1236 struct in_addr v4;
1237 struct in6_addr v6;
1238 void *addr;
1239 struct DestinationEntry *de;
1240 GNUNET_HashCode key;
1241 struct TunnelState *ts;
1242 GNUNET_MESH_ApplicationType app_type;
1243
1244 /* validate and parse request */
1245 mlen = ntohs (message->size);
1246 if (mlen < sizeof (struct RedirectToIpRequestMessage))
1247 {
1248 GNUNET_break (0);
1249 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1250 return;
1251 }
1252 alen = mlen - sizeof (struct RedirectToIpRequestMessage);
1253 msg = (const struct RedirectToIpRequestMessage *) message;
1254 addr_af = (int) htonl (msg->addr_af);
1255 switch (addr_af)
1256 {
1257 case AF_INET:
1258 if (alen != sizeof (struct in_addr))
1259 {
1260 GNUNET_break (0);
1261 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1262 return;
1263 }
1264 app_type = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY;
1265 break;
1266 case AF_INET6:
1267 if (alen != sizeof (struct in6_addr))
1268 {
1269 GNUNET_break (0);
1270 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1271 return;
1272 }
1273 app_type = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY;
1274 break;
1275 default:
1276 GNUNET_break (0);
1277 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1278 return;
1279 }
1280
1281 /* allocate response IP */
1282 addr = NULL;
1283 result_af = (int) htonl (msg->result_af);
1284 switch (result_af)
1285 {
1286 case AF_INET:
1287 if (GNUNET_OK !=
1288 allocate_v4_address (&v4))
1289 result_af = AF_UNSPEC;
1290 else
1291 addr = &v4;
1292 break;
1293 case AF_INET6:
1294 if (GNUNET_OK !=
1295 allocate_v6_address (&v6))
1296 result_af = AF_UNSPEC;
1297 else
1298 addr = &v6;
1299 break;
1300 case AF_UNSPEC:
1301 if (GNUNET_OK ==
1302 allocate_v4_address (&v4))
1303 {
1304 addr = &v4;
1305 result_af = AF_INET;
1306 }
1307 else if (GNUNET_OK ==
1308 allocate_v6_address (&v6))
1309 {
1310 addr = &v6;
1311 result_af = AF_INET6;
1312 }
1313 break;
1314 default:
1315 GNUNET_break (0);
1316 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1317 return;
1318 }
1319 if ( (result_af == AF_UNSPEC) ||
1320 (GNUNET_NO == ntohl (msg->nac)) )
1321 {
1322 /* send reply "instantly" */
1323 send_client_reply (client,
1324 msg->request_id,
1325 result_af,
1326 addr);
1327 }
1328 if (result_af == AF_UNSPEC)
1329 {
1330 /* failure, we're done */
1331 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1332 return;
1333 }
1334
1335 /* setup destination record */
1336 de = GNUNET_malloc (sizeof (struct DestinationEntry));
1337 de->is_service = GNUNET_NO;
1338 de->af = addr_af;
1339 memcpy (&de->details.ip,
1340 &msg[1],
1341 alen);
1342 get_destination_key_from_ip (result_af,
1343 addr,
1344 &key);
1345 GNUNET_assert (GNUNET_OK ==
1346 GNUNET_CONTAINER_multihashmap_put (destination_map,
1347 &key,
1348 de,
1349 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
1350 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
1351 de,
1352 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value);
1353 /* setup tunnel to destination */
1354 ts = GNUNET_malloc (sizeof (struct TunnelState));
1355 if (GNUNET_NO != ntohl (msg->nac))
1356 {
1357 ts->request_id = msg->request_id;
1358 ts->client = client;
1359 GNUNET_SERVER_client_keep (client);
1360 }
1361 ts->destination = *de;
1362 ts->destination.heap_node = NULL;
1363 ts->is_service = GNUNET_NO;
1364 ts->af = result_af;
1365 if (result_af == AF_INET)
1366 ts->destination_ip.v4 = v4;
1367 else
1368 ts->destination_ip.v6 = v6;
1369 de->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
1370 ts,
1371 &tunnel_peer_connect_handler,
1372 &tunnel_peer_disconnect_handler,
1373 ts);
1374 GNUNET_MESH_peer_request_connect_by_type (de->tunnel,
1375 app_type);
1376 /* we're done */
1377 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1082} 1378}
1083 1379
1084 1380
@@ -1095,18 +1391,27 @@ static void
1095service_redirect_to_service (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client, 1391service_redirect_to_service (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
1096 const struct GNUNET_MessageHeader *message) 1392 const struct GNUNET_MessageHeader *message)
1097{ 1393{
1394 // FIXME!
1098 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 1395 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1099} 1396}
1100 1397
1101 1398
1102 1399
1103/** 1400/**
1104 * FIXME: document. 1401 * Function called for inbound tunnels. As we don't offer
1402 * any mesh services, this function should never be called.
1403 *
1404 * @param cls closure
1405 * @param tunnel new handle to the tunnel
1406 * @param initiator peer that started the tunnel
1407 * @param atsi performance information for the tunnel
1408 * @return initial tunnel context for the tunnel
1409 * (can be NULL -- that's not an error)
1105 */ 1410 */
1106static void * 1411static void *
1107new_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel, 1412inbound_tunnel_cb (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1108 const struct GNUNET_PeerIdentity *initiator, 1413 const struct GNUNET_PeerIdentity *initiator,
1109 const struct GNUNET_ATS_Information *atsi) 1414 const struct GNUNET_ATS_Information *atsi)
1110{ 1415{
1111 /* Why should anyone open an inbound tunnel to vpn? */ 1416 /* Why should anyone open an inbound tunnel to vpn? */
1112 GNUNET_break (0); 1417 GNUNET_break (0);
@@ -1115,13 +1420,19 @@ new_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1115 1420
1116 1421
1117/** 1422/**
1118 * FIXME: document. 1423 * Function called whenever an inbound tunnel is destroyed. Should clean up
1424 * any associated state.
1425 *
1426 * @param cls closure (set from GNUNET_MESH_connect)
1427 * @param tunnel connection to the other end (henceforth invalid)
1428 * @param tunnel_ctx place where local state associated
1429 * with the tunnel is stored
1119 */ 1430 */
1120static void 1431static void
1121tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, void *tunnel_ctx) 1432tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, void *tunnel_ctx)
1122{ 1433{
1123 /* Why should anyone open an inbound tunnel to vpn? */ 1434 /* FIXME: is this function called for outbound tunnels that go down?
1124 /* FIXME: is this not also called for outbound tunnels that go down!? */ 1435 Should we clean up something here? */
1125 GNUNET_break (0); 1436 GNUNET_break (0);
1126} 1437}
1127 1438
@@ -1136,16 +1447,21 @@ cleanup (void *cls GNUNET_UNUSED,
1136 unsigned int i; 1447 unsigned int i;
1137 1448
1138 // FIXME: clean up heaps and maps! 1449 // FIXME: clean up heaps and maps!
1139 if (mesh_handle != NULL) 1450 if (NULL != mesh_handle)
1140 { 1451 {
1141 GNUNET_MESH_disconnect (mesh_handle); 1452 GNUNET_MESH_disconnect (mesh_handle);
1142 mesh_handle = NULL; 1453 mesh_handle = NULL;
1143 } 1454 }
1144 if (helper_handle != NULL) 1455 if (NULL != helper_handle)
1145 { 1456 {
1146 GNUNET_HELPER_stop (helper_handle); 1457 GNUNET_HELPER_stop (helper_handle);
1147 helper_handle = NULL; 1458 helper_handle = NULL;
1148 } 1459 }
1460 if (NULL != nc)
1461 {
1462 GNUNET_SERVER_notification_context_destroy (nc);
1463 nc = NULL;
1464 }
1149 for (i=0;i<5;i++) 1465 for (i=0;i<5;i++)
1150 GNUNET_free_non_null (vpn_argv[i]); 1466 GNUNET_free_non_null (vpn_argv[i]);
1151} 1467}
@@ -1161,7 +1477,8 @@ cleanup (void *cls GNUNET_UNUSED,
1161static void 1477static void
1162client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) 1478client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
1163{ 1479{
1164 // FIXME 1480 // FIXME: find all TunnelState's and check if they point
1481 // to the client and if so, clean the reference up!
1165} 1482}
1166 1483
1167 1484
@@ -1287,12 +1604,13 @@ run (void *cls,
1287 1604
1288 mesh_handle = 1605 mesh_handle =
1289 GNUNET_MESH_connect (cfg_, 42 /* queue length */, NULL, 1606 GNUNET_MESH_connect (cfg_, 42 /* queue length */, NULL,
1290 &new_tunnel, 1607 &inbound_tunnel_cb,
1291 &tunnel_cleaner, 1608 &tunnel_cleaner,
1292 mesh_handlers, 1609 mesh_handlers,
1293 types); 1610 types);
1294 helper_handle = GNUNET_HELPER_start ("gnunet-helper-vpn", vpn_argv, 1611 helper_handle = GNUNET_HELPER_start ("gnunet-helper-vpn", vpn_argv,
1295 &message_token, NULL); 1612 &message_token, NULL);
1613 nc = GNUNET_SERVER_notification_context_create (server, 1);
1296 GNUNET_SERVER_add_handlers (server, service_handlers); 1614 GNUNET_SERVER_add_handlers (server, service_handlers);
1297 GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL); 1615 GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL);
1298 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls); 1616 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);