aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortg(x) <*@tg-x.net>2017-02-24 20:10:46 +0100
committertg(x) <*@tg-x.net>2017-02-24 20:10:46 +0100
commitb7002d3f8016478d716236238bd43a7c06c924d2 (patch)
tree3a37e4ffc3dfbb53c7dd571b85126ec762ffbbae
parentcb1165ecfc5c89c22aa4a6fffb72e27e0bde43a3 (diff)
parentfa0b5c44f096a68ac0a51c4cbb37c920ceb36bce (diff)
downloadgnunet-b7002d3f8016478d716236238bd43a7c06c924d2.tar.gz
gnunet-b7002d3f8016478d716236238bd43a7c06c924d2.zip
Merge branch 'master' of gnunet.org:gnunet
-rwxr-xr-xcontrib/gnunet-gns-import.sh2
-rw-r--r--src/block/plugin_block_template.c2
-rw-r--r--src/cadet/gnunet-service-cadet-new_tunnels.c17
-rw-r--r--src/consensus/gnunet-service-consensus.c2
-rw-r--r--src/core/gnunet-service-core.c56
-rw-r--r--src/datastore/datastore_api.c13
-rw-r--r--src/dv/gnunet-service-dv.c2
-rw-r--r--src/exit/Makefile.am8
-rw-r--r--src/exit/gnunet-daemon-exit.c3013
-rw-r--r--src/fs/fs.conf.in2
-rw-r--r--src/fs/gnunet-service-fs.c2
-rw-r--r--src/gns/Makefile.am10
-rw-r--r--src/gns/gnunet-dns2gns.c14
-rw-r--r--src/gns/gnunet-service-gns.c5
-rw-r--r--src/identity/gnunet-identity.c64
-rw-r--r--src/include/gnunet_protocols.h19
-rw-r--r--src/include/gnunet_set_service.h51
-rw-r--r--src/namecache/.gitignore1
-rw-r--r--src/namestore/.gitignore1
-rw-r--r--src/peerstore/.gitignore1
-rw-r--r--src/pt/.gitignore5
-rw-r--r--src/pt/gnunet-daemon-pt.c3
-rw-r--r--src/pt/test_gns_vpn.c251
-rw-r--r--src/pt/test_gns_vpn.conf4
-rw-r--r--src/revocation/gnunet-service-revocation.c2
-rw-r--r--src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c1
-rw-r--r--src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c1
-rw-r--r--src/scalarproduct/gnunet-service-scalarproduct_alice.c1
-rw-r--r--src/scalarproduct/gnunet-service-scalarproduct_bob.c5
-rw-r--r--src/set/gnunet-service-set.c35
-rw-r--r--src/set/gnunet-service-set.h24
-rw-r--r--src/set/gnunet-service-set_protocol.h14
-rw-r--r--src/set/gnunet-service-set_union.c454
-rw-r--r--src/set/gnunet-set-profiler.c56
-rw-r--r--src/set/set.h48
-rw-r--r--src/set/set_api.c22
-rw-r--r--src/set/test_set.conf2
-rw-r--r--src/set/test_set_api.c3
-rw-r--r--src/set/test_set_intersection_result_full.c2
-rw-r--r--src/set/test_set_union_result_symmetric.c2
-rw-r--r--src/testing/testing.c4
-rw-r--r--src/transport/gnunet-service-transport_neighbours.c17
-rw-r--r--src/util/mq.c3
-rw-r--r--src/util/os_installation.c49
-rw-r--r--src/util/service_new.c7
45 files changed, 2536 insertions, 1764 deletions
diff --git a/contrib/gnunet-gns-import.sh b/contrib/gnunet-gns-import.sh
index 8c9d1b9d4..8614821fe 100755
--- a/contrib/gnunet-gns-import.sh
+++ b/contrib/gnunet-gns-import.sh
@@ -63,7 +63,7 @@ gnunet-identity -e master-zone -s gns-proxy $options
63 63
64# Use master-zone for intercepted DNS queries 64# Use master-zone for intercepted DNS queries
65# (remove this entry to disable DNS interception by GNS service) 65# (remove this entry to disable DNS interception by GNS service)
66gnunet-identity -e master-zone -s gns-intercept $options 66gnunet-identity -e master-zone -s dns2gns $options
67 67
68# 'gns-private' is not yet used (!) 68# 'gns-private' is not yet used (!)
69gnunet-identity -e private-zone -s gns-private $options 69gnunet-identity -e private-zone -s gns-private $options
diff --git a/src/block/plugin_block_template.c b/src/block/plugin_block_template.c
index 0825bd095..87adae7e9 100644
--- a/src/block/plugin_block_template.c
+++ b/src/block/plugin_block_template.c
@@ -111,7 +111,7 @@ block_plugin_template_create_group (void *cls,
111 } 111 }
112 GNUNET_break (NULL == va_arg (va, const char *)); 112 GNUNET_break (NULL == va_arg (va, const char *));
113 return GNUNET_BLOCK_GROUP_bf_create (cls, 113 return GNUNET_BLOCK_GROUP_bf_create (cls,
114 TEMPLATE_BF_SIZE, 114 bf_size,
115 BLOOMFILTER_K, 115 BLOOMFILTER_K,
116 type, 116 type,
117 nonce, 117 nonce,
diff --git a/src/cadet/gnunet-service-cadet-new_tunnels.c b/src/cadet/gnunet-service-cadet-new_tunnels.c
index af77ea067..bf05fae6b 100644
--- a/src/cadet/gnunet-service-cadet-new_tunnels.c
+++ b/src/cadet/gnunet-service-cadet-new_tunnels.c
@@ -603,7 +603,11 @@ GCT_count_any_connections (const struct CadetTunnel *t)
603static struct CadetTConnection * 603static struct CadetTConnection *
604get_ready_connection (struct CadetTunnel *t) 604get_ready_connection (struct CadetTunnel *t)
605{ 605{
606 return t->connection_ready_head; 606 struct CadetTConnection *hd = t->connection_ready_head;
607
608 GNUNET_assert ( (NULL == hd) ||
609 (GNUNET_YES == hd->is_ready) );
610 return hd;
607} 611}
608 612
609 613
@@ -1315,7 +1319,8 @@ send_kx (struct CadetTunnel *t,
1315 struct GNUNET_CADET_TunnelKeyExchangeMessage *msg; 1319 struct GNUNET_CADET_TunnelKeyExchangeMessage *msg;
1316 enum GNUNET_CADET_KX_Flags flags; 1320 enum GNUNET_CADET_KX_Flags flags;
1317 1321
1318 if (NULL == ct) 1322 if ( (NULL == ct) ||
1323 (GNUNET_NO == ct->is_ready) )
1319 ct = get_ready_connection (t); 1324 ct = get_ready_connection (t);
1320 if (NULL == ct) 1325 if (NULL == ct)
1321 { 1326 {
@@ -1825,7 +1830,7 @@ GCT_handle_kx_auth (struct CadetTConnection *ct,
1825 1, 1830 1,
1826 GNUNET_NO); 1831 GNUNET_NO);
1827 send_kx (t, 1832 send_kx (t,
1828 NULL, 1833 ct,
1829 &t->ax); 1834 &t->ax);
1830 return; 1835 return;
1831 } 1836 }
@@ -1971,13 +1976,19 @@ GCT_connection_lost (struct CadetTConnection *ct)
1971 struct CadetTunnel *t = ct->t; 1976 struct CadetTunnel *t = ct->t;
1972 1977
1973 if (GNUNET_YES == ct->is_ready) 1978 if (GNUNET_YES == ct->is_ready)
1979 {
1974 GNUNET_CONTAINER_DLL_remove (t->connection_ready_head, 1980 GNUNET_CONTAINER_DLL_remove (t->connection_ready_head,
1975 t->connection_ready_tail, 1981 t->connection_ready_tail,
1976 ct); 1982 ct);
1983 t->num_ready_connections--;
1984 }
1977 else 1985 else
1986 {
1978 GNUNET_CONTAINER_DLL_remove (t->connection_busy_head, 1987 GNUNET_CONTAINER_DLL_remove (t->connection_busy_head,
1979 t->connection_busy_tail, 1988 t->connection_busy_tail,
1980 ct); 1989 ct);
1990 t->num_busy_connections--;
1991 }
1981 GNUNET_free (ct); 1992 GNUNET_free (ct);
1982} 1993}
1983 1994
diff --git a/src/consensus/gnunet-service-consensus.c b/src/consensus/gnunet-service-consensus.c
index 16ca6a57f..4036d2b11 100644
--- a/src/consensus/gnunet-service-consensus.c
+++ b/src/consensus/gnunet-service-consensus.c
@@ -2013,6 +2013,7 @@ task_start_reconcile (struct TaskEntry *task)
2013 &session->global_id, 2013 &session->global_id,
2014 &rcm.header, 2014 &rcm.header,
2015 GNUNET_SET_RESULT_SYMMETRIC, 2015 GNUNET_SET_RESULT_SYMMETRIC,
2016 (struct GNUNET_SET_Option[]) { 0 },
2016 set_result_cb, 2017 set_result_cb,
2017 task); 2018 task);
2018 2019
@@ -2439,6 +2440,7 @@ set_listen_cb (void *cls,
2439 2440
2440 task->cls.setop.op = GNUNET_SET_accept (request, 2441 task->cls.setop.op = GNUNET_SET_accept (request,
2441 GNUNET_SET_RESULT_SYMMETRIC, 2442 GNUNET_SET_RESULT_SYMMETRIC,
2443 (struct GNUNET_SET_Option[]) { 0 },
2442 set_result_cb, 2444 set_result_cb,
2443 task); 2445 task);
2444 2446
diff --git a/src/core/gnunet-service-core.c b/src/core/gnunet-service-core.c
index 52c6f72ab..31b91f12f 100644
--- a/src/core/gnunet-service-core.c
+++ b/src/core/gnunet-service-core.c
@@ -32,11 +32,19 @@
32#include "gnunet-service-core_typemap.h" 32#include "gnunet-service-core_typemap.h"
33 33
34/** 34/**
35 * How many messages do we queue up at most for optional 35 * How many messages do we queue up at most for any client? This can
36 * notifications to a client? (this can cause notifications 36 * cause messages to be dropped if clients do not process them fast
37 * about outgoing messages to be dropped). 37 * enough! Note that this is a soft limit; we try
38 * to keep a few larger messages above the limit.
38 */ 39 */
39#define MAX_NOTIFY_QUEUE 1024 40#define SOFT_MAX_QUEUE 128
41
42/**
43 * How many messages do we queue up at most for any client? This can
44 * cause messages to be dropped if clients do not process them fast
45 * enough! Note that this is the hard limit.
46 */
47#define HARD_MAX_QUEUE 256
40 48
41 49
42/** 50/**
@@ -819,6 +827,7 @@ GSC_CLIENTS_deliver_message (const struct GNUNET_PeerIdentity *sender,
819 struct GNUNET_MQ_Envelope *env; 827 struct GNUNET_MQ_Envelope *env;
820 struct NotifyTrafficMessage *ntm; 828 struct NotifyTrafficMessage *ntm;
821 uint16_t mtype; 829 uint16_t mtype;
830 unsigned int qlen;
822 int tm; 831 int tm;
823 832
824 tm = type_match (ntohs (msg->type), 833 tm = type_match (ntohs (msg->type),
@@ -834,6 +843,45 @@ GSC_CLIENTS_deliver_message (const struct GNUNET_PeerIdentity *sender,
834 if ( (0 != (options & GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND)) && 843 if ( (0 != (options & GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND)) &&
835 (0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND)) ) 844 (0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND)) )
836 continue; 845 continue;
846
847 /* Drop messages if:
848 1) We are above the hard limit, or
849 2) We are above the soft limit, and a coin toss limited
850 to the message size (giving larger messages a
851 proportionally higher chance of being queued) falls
852 below the threshold. The threshold is based on where
853 we are between the soft and the hard limit, scaled
854 to match the range of message sizes we usually encounter
855 (i.e. up to 32k); so a 64k message has a 50% chance of
856 being kept if we are just barely below the hard max,
857 and a 99% chance of being kept if we are at the soft max.
858 The reason is to make it more likely to drop control traffic
859 (ACK, queries) which may be cummulative or highly redundant,
860 and cheap to drop than data traffic. */
861 qlen = GNUNET_MQ_get_length (c->mq);
862 if ( (qlen >= HARD_MAX_QUEUE) ||
863 ( (qlen > SOFT_MAX_QUEUE) &&
864 ( (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
865 ntohs (msg->size)) ) <
866 (qlen - SOFT_MAX_QUEUE) * 0x8000 /
867 (HARD_MAX_QUEUE - SOFT_MAX_QUEUE) ) ) )
868 {
869 char buf[1024];
870
871 GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
872 "Dropping decrypted message of type %u as client is too busy (queue full)\n",
873 (unsigned int) ntohs (msg->type));
874 GNUNET_snprintf (buf,
875 sizeof (buf),
876 gettext_noop ("# messages of type %u discarded (client busy)"),
877 (unsigned int) ntohs (msg->type));
878 GNUNET_STATISTICS_update (GSC_stats,
879 buf,
880 1,
881 GNUNET_NO);
882 continue;
883 }
884
837 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 885 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
838 "Sending %u message with %u bytes to client interested in messages of type %u.\n", 886 "Sending %u message with %u bytes to client interested in messages of type %u.\n",
839 options, 887 options,
diff --git a/src/datastore/datastore_api.c b/src/datastore/datastore_api.c
index 311a61283..916e6acae 100644
--- a/src/datastore/datastore_api.c
+++ b/src/datastore/datastore_api.c
@@ -498,8 +498,17 @@ make_queue_entry (struct GNUNET_DATASTORE_Handle *h,
498 struct GNUNET_DATASTORE_QueueEntry *pos; 498 struct GNUNET_DATASTORE_QueueEntry *pos;
499 unsigned int c; 499 unsigned int c;
500 500
501 c = 0; 501 if ( (NULL != h->queue_tail) &&
502 pos = h->queue_head; 502 (h->queue_tail->priority >= queue_priority) )
503 {
504 c = h->queue_size;
505 pos = NULL;
506 }
507 else
508 {
509 c = 0;
510 pos = h->queue_head;
511 }
503 while ( (NULL != pos) && 512 while ( (NULL != pos) &&
504 (c < max_queue_size) && 513 (c < max_queue_size) &&
505 (pos->priority >= queue_priority) ) 514 (pos->priority >= queue_priority) )
diff --git a/src/dv/gnunet-service-dv.c b/src/dv/gnunet-service-dv.c
index 6adaa04d9..e4b664f4b 100644
--- a/src/dv/gnunet-service-dv.c
+++ b/src/dv/gnunet-service-dv.c
@@ -1528,6 +1528,7 @@ listen_set_union (void *cls,
1528 GNUNET_SET_OPERATION_UNION); 1528 GNUNET_SET_OPERATION_UNION);
1529 neighbor->set_op = GNUNET_SET_accept (request, 1529 neighbor->set_op = GNUNET_SET_accept (request,
1530 GNUNET_SET_RESULT_ADDED, 1530 GNUNET_SET_RESULT_ADDED,
1531 (struct GNUNET_SET_Option[]) { 0 },
1531 &handle_set_union_result, 1532 &handle_set_union_result,
1532 neighbor); 1533 neighbor);
1533 neighbor->consensus_insertion_offset = 0; 1534 neighbor->consensus_insertion_offset = 0;
@@ -1558,6 +1559,7 @@ initiate_set_union (void *cls)
1558 &neighbor->real_session_id, 1559 &neighbor->real_session_id,
1559 NULL, 1560 NULL,
1560 GNUNET_SET_RESULT_ADDED, 1561 GNUNET_SET_RESULT_ADDED,
1562 (struct GNUNET_SET_Option[]) { 0 },
1561 &handle_set_union_result, 1563 &handle_set_union_result,
1562 neighbor); 1564 neighbor);
1563 neighbor->consensus_insertion_offset = 0; 1565 neighbor->consensus_insertion_offset = 0;
diff --git a/src/exit/Makefile.am b/src/exit/Makefile.am
index 6c4cbf114..271b4ebd7 100644
--- a/src/exit/Makefile.am
+++ b/src/exit/Makefile.am
@@ -30,11 +30,11 @@ endif
30 30
31libexec_PROGRAMS = \ 31libexec_PROGRAMS = \
32 gnunet-daemon-exit \ 32 gnunet-daemon-exit \
33 $(EXITBIN) 33 $(EXITBIN)
34 34
35if MINGW 35if MINGW
36 gnunet_helper_exit_LDFLAGS = \ 36 gnunet_helper_exit_LDFLAGS = \
37 -no-undefined -Wl,--export-all-symbols 37 -no-undefined -Wl,--export-all-symbols
38 38
39 gnunet_helper_exit_LDADD = \ 39 gnunet_helper_exit_LDADD = \
40 -lsetupapi -lnewdev -lshell32 -liconv -lstdc++ \ 40 -lsetupapi -lnewdev -lshell32 -liconv -lstdc++ \
@@ -47,13 +47,13 @@ else
47 gnunet-helper-exit.c 47 gnunet-helper-exit.c
48endif 48endif
49gnunet_daemon_exit_SOURCES = \ 49gnunet_daemon_exit_SOURCES = \
50 gnunet-daemon-exit.c exit.h 50 gnunet-daemon-exit.c exit.h
51gnunet_daemon_exit_LDADD = \ 51gnunet_daemon_exit_LDADD = \
52 $(top_builddir)/src/dns/libgnunetdnsstub.la \ 52 $(top_builddir)/src/dns/libgnunetdnsstub.la \
53 $(top_builddir)/src/dht/libgnunetdht.la \ 53 $(top_builddir)/src/dht/libgnunetdht.la \
54 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 54 $(top_builddir)/src/statistics/libgnunetstatistics.la \
55 $(top_builddir)/src/tun/libgnunettun.la \ 55 $(top_builddir)/src/tun/libgnunettun.la \
56 $(top_builddir)/src/util/libgnunetutil.la \ 56 $(top_builddir)/src/util/libgnunetutil.la \
57 $(top_builddir)/src/cadet/libgnunetcadet.la \ 57 $(top_builddir)/src/cadet/libgnunetcadetnew.la \
58 $(top_builddir)/src/regex/libgnunetregex.la \ 58 $(top_builddir)/src/regex/libgnunetregex.la \
59 $(GN_LIBINTL) 59 $(GN_LIBINTL)
diff --git a/src/exit/gnunet-daemon-exit.c b/src/exit/gnunet-daemon-exit.c
index 92acc61cd..09576e393 100644
--- a/src/exit/gnunet-daemon-exit.c
+++ b/src/exit/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 Copyright (C) 2010-2013 Christian Grothoff 3 Copyright (C) 2010-2013, 2017 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
@@ -195,33 +195,6 @@ struct RedirectInformation
195 195
196 196
197/** 197/**
198 * Queue of messages to a channel.
199 */
200struct ChannelMessageQueue
201{
202 /**
203 * This is a doubly-linked list.
204 */
205 struct ChannelMessageQueue *next;
206
207 /**
208 * This is a doubly-linked list.
209 */
210 struct ChannelMessageQueue *prev;
211
212 /**
213 * Payload to send via the channel.
214 */
215 const void *payload;
216
217 /**
218 * Number of bytes in @e payload.
219 */
220 size_t len;
221};
222
223
224/**
225 * This struct is saved into #connections_map to allow finding the 198 * This struct is saved into #connections_map to allow finding the
226 * right channel given an IP packet from TUN. It is also associated 199 * right channel given an IP packet from TUN. It is also associated
227 * with the channel's closure so we can find it again for the next 200 * with the channel's closure so we can find it again for the next
@@ -241,11 +214,6 @@ struct ChannelState
241 struct GNUNET_PeerIdentity peer; 214 struct GNUNET_PeerIdentity peer;
242 215
243 /** 216 /**
244 * Active channel transmission request (or NULL).
245 */
246 struct GNUNET_CADET_TransmitHandle *th;
247
248 /**
249 * #GNUNET_NO if this is a channel for TCP/UDP, 217 * #GNUNET_NO if this is a channel for TCP/UDP,
250 * #GNUNET_YES if this is a channel for DNS, 218 * #GNUNET_YES if this is a channel for DNS,
251 * #GNUNET_SYSERR if the channel is not yet initialized. 219 * #GNUNET_SYSERR if the channel is not yet initialized.
@@ -273,16 +241,6 @@ struct ChannelState
273 struct LocalService *serv; 241 struct LocalService *serv;
274 242
275 /** 243 /**
276 * Head of DLL of messages for this channel.
277 */
278 struct ChannelMessageQueue *head;
279
280 /**
281 * Tail of DLL of messages for this channel.
282 */
283 struct ChannelMessageQueue *tail;
284
285 /**
286 * Primary redirection information for this connection. 244 * Primary redirection information for this connection.
287 */ 245 */
288 struct RedirectInformation ri; 246 struct RedirectInformation ri;
@@ -292,22 +250,12 @@ struct ChannelState
292 { 250 {
293 251
294 /** 252 /**
295 * DNS reply ready for transmission.
296 */
297 char *reply;
298
299 /**
300 * Socket we are using to transmit this request (must match if we receive 253 * Socket we are using to transmit this request (must match if we receive
301 * a response). 254 * a response).
302 */ 255 */
303 struct GNUNET_DNSSTUB_RequestSocket *rs; 256 struct GNUNET_DNSSTUB_RequestSocket *rs;
304 257
305 /** 258 /**
306 * Number of bytes in 'reply'.
307 */
308 size_t reply_length;
309
310 /**
311 * Original DNS request ID as used by the client. 259 * Original DNS request ID as used by the client.
312 */ 260 */
313 uint16_t original_id; 261 uint16_t original_id;
@@ -428,7 +376,7 @@ static struct GNUNET_DHT_Handle *dht;
428/** 376/**
429 * Task for doing DHT PUTs to advertise exit service. 377 * Task for doing DHT PUTs to advertise exit service.
430 */ 378 */
431static struct GNUNET_SCHEDULER_Task * dht_task; 379static struct GNUNET_SCHEDULER_Task *dht_task;
432 380
433/** 381/**
434 * Advertisement message we put into the DHT to advertise us 382 * Advertisement message we put into the DHT to advertise us
@@ -447,6 +395,21 @@ static struct GNUNET_HashCode dht_put_key;
447static struct GNUNET_CRYPTO_EddsaPrivateKey *peer_key; 395static struct GNUNET_CRYPTO_EddsaPrivateKey *peer_key;
448 396
449/** 397/**
398 * Port for DNS exit.
399 */
400static struct GNUNET_CADET_Port *dns_port;
401
402/**
403 * Port for IPv4 exit.
404 */
405static struct GNUNET_CADET_Port *cadet_port4;
406
407/**
408 * Port for IPv6 exit.
409 */
410static struct GNUNET_CADET_Port *cadet_port6;
411
412/**
450 * Are we an IPv4-exit? 413 * Are we an IPv4-exit?
451 */ 414 */
452static int ipv4_exit; 415static int ipv4_exit;
@@ -467,51 +430,27 @@ static int ipv4_enabled;
467static int ipv6_enabled; 430static int ipv6_enabled;
468 431
469 432
433GNUNET_NETWORK_STRUCT_BEGIN
434
470/** 435/**
471 * We got a reply from DNS for a request of a CADET channel. Send it 436 * Message with a DNS response.
472 * via the channel (after changing the request ID back). 437 */
473 * 438struct DnsResponseMessage
474 * @param cls the `struct ChannelState`
475 * @param size number of bytes available in @a buf
476 * @param buf where to copy the reply
477 * @return number of bytes written to @a buf
478 */
479static size_t
480transmit_reply_to_cadet (void *cls,
481 size_t size,
482 void *buf)
483{ 439{
484 struct ChannelState *ts = cls; 440 /**
485 size_t off; 441 * GNUnet header, of type #GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET
486 size_t ret; 442 */
487 char *cbuf = buf; 443 struct GNUNET_MessageHeader header;
488 struct GNUNET_MessageHeader hdr; 444
445 /**
446 * DNS header.
447 */
489 struct GNUNET_TUN_DnsHeader dns; 448 struct GNUNET_TUN_DnsHeader dns;
490 449
491 GNUNET_assert (GNUNET_YES == ts->is_dns); 450 /* Followed by more DNS payload */
492 ts->th = NULL; 451};
493 GNUNET_assert (ts->specifics.dns.reply != NULL); 452
494 if (size == 0) 453GNUNET_NETWORK_STRUCT_END
495 return 0;
496 ret = sizeof (struct GNUNET_MessageHeader) + ts->specifics.dns.reply_length;
497 GNUNET_assert (ret <= size);
498 hdr.size = htons (ret);
499 hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET);
500 GNUNET_memcpy (&dns, ts->specifics.dns.reply, sizeof (dns));
501 dns.id = ts->specifics.dns.original_id;
502 off = 0;
503 GNUNET_memcpy (&cbuf[off], &hdr, sizeof (hdr));
504 off += sizeof (hdr);
505 GNUNET_memcpy (&cbuf[off], &dns, sizeof (dns));
506 off += sizeof (dns);
507 GNUNET_memcpy (&cbuf[off], &ts->specifics.dns.reply[sizeof (dns)], ts->specifics.dns.reply_length - sizeof (dns));
508 off += ts->specifics.dns.reply_length - sizeof (dns);
509 GNUNET_free (ts->specifics.dns.reply);
510 ts->specifics.dns.reply = NULL;
511 ts->specifics.dns.reply_length = 0;
512 GNUNET_assert (ret == off);
513 return ret;
514}
515 454
516 455
517/** 456/**
@@ -521,7 +460,7 @@ transmit_reply_to_cadet (void *cls,
521 * @param cls NULL 460 * @param cls NULL
522 * @param rs the socket that received the response 461 * @param rs the socket that received the response
523 * @param dns the response itself 462 * @param dns the response itself
524 * @param r number of bytes in dns 463 * @param r number of bytes in @a dns
525 */ 464 */
526static void 465static void
527process_dns_result (void *cls, 466process_dns_result (void *cls,
@@ -530,6 +469,8 @@ process_dns_result (void *cls,
530 size_t r) 469 size_t r)
531{ 470{
532 struct ChannelState *ts; 471 struct ChannelState *ts;
472 struct GNUNET_MQ_Envelope *env;
473 struct DnsResponseMessage *resp;
533 474
534 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 475 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
535 "Processing DNS result from stub resolver\n"); 476 "Processing DNS result from stub resolver\n");
@@ -542,48 +483,35 @@ process_dns_result (void *cls,
542 LOG (GNUNET_ERROR_TYPE_DEBUG, 483 LOG (GNUNET_ERROR_TYPE_DEBUG,
543 "Got a response from the stub resolver for DNS request received via CADET!\n"); 484 "Got a response from the stub resolver for DNS request received via CADET!\n");
544 channels[dns->id] = NULL; 485 channels[dns->id] = NULL;
545 GNUNET_free_non_null (ts->specifics.dns.reply); 486 env = GNUNET_MQ_msg_extra (resp,
546 ts->specifics.dns.reply = GNUNET_malloc (r); 487 r - sizeof (struct GNUNET_TUN_DnsHeader),
547 ts->specifics.dns.reply_length = r; 488 GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET);
548 GNUNET_memcpy (ts->specifics.dns.reply, dns, r); 489 GNUNET_memcpy (&resp->dns,
549 if (NULL != ts->th) 490 dns,
550 GNUNET_CADET_notify_transmit_ready_cancel (ts->th); 491 r);
551 ts->th = GNUNET_CADET_notify_transmit_ready (ts->channel, 492 resp->dns.id = ts->specifics.dns.original_id;
552 GNUNET_NO, 493 GNUNET_MQ_send (GNUNET_CADET_get_mq (ts->channel),
553 GNUNET_TIME_UNIT_FOREVER_REL, 494 env);
554 sizeof (struct GNUNET_MessageHeader) + r,
555 &transmit_reply_to_cadet,
556 ts);
557} 495}
558 496
559 497
560/** 498/**
561 * Process a request via cadet to perform a DNS query. 499 * Check a request via cadet to perform a DNS query.
562 *
563 * @param cls closure, NULL
564 * @param channel connection to the other end
565 * @param channel_ctx pointer to our `struct ChannelState *`
566 * @param message the actual message
567 * 500 *
501 * @param cls our `struct ChannelState *`
502 * @param msg the actual message
568 * @return #GNUNET_OK to keep the connection open, 503 * @return #GNUNET_OK to keep the connection open,
569 * #GNUNET_SYSERR to close it (signal serious error) 504 * #GNUNET_SYSERR to close it (signal serious error)
570 */ 505 */
571static int 506static int
572receive_dns_request (void *cls GNUNET_UNUSED, 507check_dns_request (void *cls,
573 struct GNUNET_CADET_Channel *channel, 508 const struct DnsResponseMessage *msg)
574 void **channel_ctx,
575 const struct GNUNET_MessageHeader *message)
576{ 509{
577 struct ChannelState *ts = *channel_ctx; 510 struct ChannelState *ts = cls;
578 const struct GNUNET_TUN_DnsHeader *dns;
579 size_t mlen = ntohs (message->size);
580 size_t dlen = mlen - sizeof (struct GNUNET_MessageHeader);
581 char buf[dlen] GNUNET_ALIGN;
582 struct GNUNET_TUN_DnsHeader *dout;
583 511
584 if (NULL == dnsstub) 512 if (NULL == dnsstub)
585 { 513 {
586 GNUNET_break_op (0); 514 GNUNET_break (0);
587 return GNUNET_SYSERR; 515 return GNUNET_SYSERR;
588 } 516 }
589 if (GNUNET_NO == ts->is_dns) 517 if (GNUNET_NO == ts->is_dns)
@@ -591,34 +519,53 @@ receive_dns_request (void *cls GNUNET_UNUSED,
591 GNUNET_break_op (0); 519 GNUNET_break_op (0);
592 return GNUNET_SYSERR; 520 return GNUNET_SYSERR;
593 } 521 }
522 return GNUNET_OK;
523}
524
525
526/**
527 * Process a request via cadet to perform a DNS query.
528 *
529 * @param cls our `struct ChannelState *`
530 * @param msg the actual message
531 */
532static void
533handle_dns_request (void *cls,
534 const struct DnsResponseMessage *msg)
535{
536 struct ChannelState *ts = cls;
537 size_t mlen = ntohs (msg->header.size);
538 size_t dlen = mlen - sizeof (struct GNUNET_MessageHeader);
539 char buf[dlen] GNUNET_ALIGN;
540 struct GNUNET_TUN_DnsHeader *dout;
541
594 if (GNUNET_SYSERR == ts->is_dns) 542 if (GNUNET_SYSERR == ts->is_dns)
595 { 543 {
596 /* channel is DNS from now on */ 544 /* channel is DNS from now on */
597 ts->is_dns = GNUNET_YES; 545 ts->is_dns = GNUNET_YES;
598 } 546 }
599 if (dlen < sizeof (struct GNUNET_TUN_DnsHeader)) 547 ts->specifics.dns.original_id = msg->dns.id;
600 {
601 GNUNET_break_op (0);
602 return GNUNET_SYSERR;
603 }
604 dns = (const struct GNUNET_TUN_DnsHeader *) &message[1];
605 ts->specifics.dns.original_id = dns->id;
606 if (channels[ts->specifics.dns.my_id] == ts) 548 if (channels[ts->specifics.dns.my_id] == ts)
607 channels[ts->specifics.dns.my_id] = NULL; 549 channels[ts->specifics.dns.my_id] = NULL;
608 ts->specifics.dns.my_id = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 550 ts->specifics.dns.my_id = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
609 UINT16_MAX + 1); 551 UINT16_MAX + 1);
610 channels[ts->specifics.dns.my_id] = ts; 552 channels[ts->specifics.dns.my_id] = ts;
611 GNUNET_memcpy (buf, dns, dlen); 553 GNUNET_memcpy (buf,
554 &msg->dns,
555 dlen);
612 dout = (struct GNUNET_TUN_DnsHeader *) buf; 556 dout = (struct GNUNET_TUN_DnsHeader *) buf;
613 dout->id = ts->specifics.dns.my_id; 557 dout->id = ts->specifics.dns.my_id;
614 ts->specifics.dns.rs = GNUNET_DNSSTUB_resolve2 (dnsstub, 558 ts->specifics.dns.rs = GNUNET_DNSSTUB_resolve2 (dnsstub,
615 buf, dlen, 559 buf,
560 dlen,
616 &process_dns_result, 561 &process_dns_result,
617 NULL); 562 NULL);
618 if (NULL == ts->specifics.dns.rs) 563 if (NULL == ts->specifics.dns.rs)
619 return GNUNET_SYSERR; 564 {
620 GNUNET_CADET_receive_done (channel); 565 GNUNET_break_op (0);
621 return GNUNET_OK; 566 return;
567 }
568 GNUNET_CADET_receive_done (ts->channel);
622} 569}
623 570
624 571
@@ -753,706 +700,445 @@ get_redirect_state (int af,
753} 700}
754 701
755 702
756/**
757 * Free memory associated with a service record.
758 *
759 * @param cls unused
760 * @param key service descriptor
761 * @param value service record to free
762 * @return #GNUNET_OK
763 */
764static int
765free_service_record (void *cls,
766 const struct GNUNET_HashCode *key,
767 void *value)
768{
769 struct LocalService *service = value;
770
771 GNUNET_assert (GNUNET_YES ==
772 GNUNET_CONTAINER_multihashmap_remove (services,
773 key,
774 service));
775 GNUNET_CADET_close_port (service->port);
776 GNUNET_free_non_null (service->name);
777 GNUNET_free (service);
778 return GNUNET_OK;
779}
780
781
782/**
783 * Callback from CADET for new channels.
784 *
785 * @param cls closure
786 * @param channel new handle to the channel
787 * @param initiator peer that started the channel
788 * @param port destination port
789 * @param options channel options flags
790 * @return initial channel context for the channel
791 */
792static void *
793new_service_channel (void *cls,
794 struct GNUNET_CADET_Channel *channel,
795 const struct GNUNET_PeerIdentity *initiator,
796 const struct GNUNET_HashCode *port,
797 enum GNUNET_CADET_ChannelOption options)
798{
799 struct LocalService *ls = cls;
800 struct ChannelState *s = GNUNET_new (struct ChannelState);
801
802 s->peer = *initiator;
803 GNUNET_STATISTICS_update (stats,
804 gettext_noop ("# Inbound CADET channels created"),
805 1,
806 GNUNET_NO);
807 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
808 "Received inbound channel from `%s'\n",
809 GNUNET_i2s (initiator));
810 s->channel = channel;
811 s->specifics.tcp_udp.serv = ls;
812 s->specifics.tcp_udp.ri.remote_address = ls->address;
813 return s;
814}
815
816 703
817/** 704/**
818 * Given a service descriptor and a destination port, find the 705 * Check a request via cadet to send a request to a TCP service
819 * respective service entry. 706 * offered by this system.
820 * 707 *
821 * @param proto IPPROTO_TCP or IPPROTO_UDP 708 * @param cls our `struct ChannelState *`
822 * @param name name of the service 709 * @param start the actual message
823 * @param destination_port destination port 710 * @return #GNUNET_OK to keep the connection open,
824 * @param service service information record to store (service->name will be set). 711 * #GNUNET_SYSERR to close it (signal serious error)
825 */ 712 */
826static void 713static int
827store_service (int proto, 714check_tcp_service (void *cls,
828 const char *name, 715 const struct GNUNET_EXIT_TcpServiceStartMessage *start)
829 uint16_t destination_port,
830 struct LocalService *service)
831{ 716{
832 struct GNUNET_HashCode cadet_port; 717 struct ChannelState *state = cls;
833 718
834 service->name = GNUNET_strdup (name); 719 if (NULL == state)
835 GNUNET_TUN_service_name_to_hash (name,
836 &service->descriptor);
837 GNUNET_TUN_compute_service_cadet_port (&service->descriptor,
838 destination_port,
839 &cadet_port);
840 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
841 "Opening CADET port %s for SERVICE exit %s on port %u\n",
842 GNUNET_h2s (&cadet_port),
843 name,
844 (unsigned int) destination_port);
845 service->port = GNUNET_CADET_open_port (cadet_handle,
846 &cadet_port,
847 &new_service_channel,
848 service);
849 service->is_udp = (IPPROTO_UDP == proto);
850 if (GNUNET_OK !=
851 GNUNET_CONTAINER_multihashmap_put (services,
852 &cadet_port,
853 service,
854 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
855 { 720 {
856 GNUNET_CADET_close_port (service->port); 721 GNUNET_break_op (0);
857 GNUNET_free_non_null (service->name); 722 return GNUNET_SYSERR;
858 GNUNET_free (service);
859 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
860 _("Got duplicate service records for `%s:%u'\n"),
861 name,
862 (unsigned int) destination_port);
863 } 723 }
724 if (GNUNET_YES == state->is_dns)
725 {
726 GNUNET_break_op (0);
727 return GNUNET_SYSERR;
728 }
729 if (NULL == state->specifics.tcp_udp.serv)
730 {
731 GNUNET_break_op (0);
732 return GNUNET_SYSERR;
733 }
734 if (NULL != state->specifics.tcp_udp.heap_node)
735 {
736 GNUNET_break_op (0);
737 return GNUNET_SYSERR;
738 }
739 if (start->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
740 {
741 GNUNET_break_op (0);
742 return GNUNET_SYSERR;
743 }
744 return GNUNET_OK;
864} 745}
865 746
866 747
867/** 748/**
868 * CADET is ready to receive a message for the channel. Transmit it. 749 * Prepare an IPv4 packet for transmission via the TUN interface.
869 * 750 * Initializes the IP header and calculates checksums (IP+UDP/TCP).
870 * @param cls the `struct ChannelState`. 751 * For UDP, the UDP header will be fully created, whereas for TCP
871 * @param size number of bytes available in @a buf 752 * only the ports and checksum will be filled in. So for TCP,
872 * @param buf where to copy the message 753 * a skeleton TCP header must be part of the provided payload.
873 * @return number of bytes copied to @a buf
874 */
875static size_t
876send_to_peer_notify_callback (void *cls,
877 size_t size,
878 void *buf)
879{
880 struct ChannelState *s = cls;
881 struct GNUNET_CADET_Channel *channel = s->channel;
882 struct ChannelMessageQueue *tnq;
883
884 s->th = NULL;
885 tnq = s->specifics.tcp_udp.head;
886 if (NULL == tnq)
887 return 0;
888 if (0 == size)
889 {
890 s->th = GNUNET_CADET_notify_transmit_ready (channel,
891 GNUNET_NO /* corking */,
892 GNUNET_TIME_UNIT_FOREVER_REL,
893 tnq->len,
894 &send_to_peer_notify_callback,
895 s);
896 return 0;
897 }
898 GNUNET_assert (size >= tnq->len);
899 GNUNET_memcpy (buf, tnq->payload, tnq->len);
900 size = tnq->len;
901 GNUNET_CONTAINER_DLL_remove (s->specifics.tcp_udp.head,
902 s->specifics.tcp_udp.tail,
903 tnq);
904 GNUNET_free (tnq);
905 if (NULL != (tnq = s->specifics.tcp_udp.head))
906 s->th = GNUNET_CADET_notify_transmit_ready (channel,
907 GNUNET_NO /* corking */,
908 GNUNET_TIME_UNIT_FOREVER_REL,
909 tnq->len,
910 &send_to_peer_notify_callback,
911 s);
912 GNUNET_STATISTICS_update (stats,
913 gettext_noop ("# Bytes transmitted via cadet channels"),
914 size, GNUNET_NO);
915 return size;
916}
917
918
919/**
920 * Send the given packet via the cadet channel.
921 *
922 * @param s channel destination
923 * @param tnq message to queue
924 */
925static void
926send_packet_to_cadet_channel (struct ChannelState *s,
927 struct ChannelMessageQueue *tnq)
928{
929 struct GNUNET_CADET_Channel *cadet_channel;
930
931 cadet_channel = s->channel;
932 GNUNET_assert (NULL != s);
933 GNUNET_CONTAINER_DLL_insert_tail (s->specifics.tcp_udp.head,
934 s->specifics.tcp_udp.tail,
935 tnq);
936 if (NULL == s->th)
937 s->th = GNUNET_CADET_notify_transmit_ready (cadet_channel,
938 GNUNET_NO /* cork */,
939 GNUNET_TIME_UNIT_FOREVER_REL,
940 tnq->len,
941 &send_to_peer_notify_callback,
942 s);
943}
944
945
946/**
947 * @brief Handles an ICMP packet received from the helper.
948 * 754 *
949 * @param icmp A pointer to the Packet 755 * @param payload payload of the packet (starting with UDP payload or
950 * @param pktlen number of bytes in @a icmp 756 * TCP header, depending on protocol)
951 * @param af address family (AFINET or AF_INET6) 757 * @param payload_length number of bytes in @a payload
952 * @param destination_ip destination IP-address of the IP packet (should 758 * @param protocol IPPROTO_UDP or IPPROTO_TCP
953 * be our local address) 759 * @param tcp_header skeleton of the TCP header, NULL for UDP
954 * @param source_ip original source IP-address of the IP packet (should 760 * @param src_address source address to use (IP and port)
955 * be the original destination address) 761 * @param dst_address destination address to use (IP and port)
762 * @param pkt4 where to write the assembled packet; must
763 * contain enough space for the IP header, UDP/TCP header
764 * AND the payload
956 */ 765 */
957static void 766static void
958icmp_from_helper (const struct GNUNET_TUN_IcmpHeader *icmp, 767prepare_ipv4_packet (const void *payload,
959 size_t pktlen, 768 size_t payload_length,
960 int af, 769 int protocol,
961 const void *destination_ip, 770 const struct GNUNET_TUN_TcpHeader *tcp_header,
962 const void *source_ip) 771 const struct SocketAddress *src_address,
772 const struct SocketAddress *dst_address,
773 struct GNUNET_TUN_IPv4Header *pkt4)
963{ 774{
964 struct ChannelState *state; 775 size_t len;
965 struct ChannelMessageQueue *tnq;
966 struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
967 const struct GNUNET_TUN_IPv4Header *ipv4;
968 const struct GNUNET_TUN_IPv6Header *ipv6;
969 const struct GNUNET_TUN_UdpHeader *udp;
970 size_t mlen;
971 uint16_t source_port;
972 uint16_t destination_port;
973 uint8_t protocol;
974 776
777 len = payload_length;
778 switch (protocol)
975 { 779 {
976 char sbuf[INET6_ADDRSTRLEN]; 780 case IPPROTO_UDP:
977 char dbuf[INET6_ADDRSTRLEN]; 781 len += sizeof (struct GNUNET_TUN_UdpHeader);
978 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 782 break;
979 "Received ICMP packet going from %s to %s\n", 783 case IPPROTO_TCP:
980 inet_ntop (af, 784 len += sizeof (struct GNUNET_TUN_TcpHeader);
981 source_ip, 785 GNUNET_assert (NULL != tcp_header);
982 sbuf, sizeof (sbuf)), 786 break;
983 inet_ntop (af, 787 default:
984 destination_ip, 788 GNUNET_break (0);
985 dbuf, sizeof (dbuf))); 789 return;
986 } 790 }
987 if (pktlen < sizeof (struct GNUNET_TUN_IcmpHeader)) 791 if (len + sizeof (struct GNUNET_TUN_IPv4Header) > UINT16_MAX)
988 { 792 {
989 /* blame kernel */
990 GNUNET_break (0); 793 GNUNET_break (0);
991 return; 794 return;
992 } 795 }
993 796
994 /* Find out if this is an ICMP packet in response to an existing 797 GNUNET_TUN_initialize_ipv4_header (pkt4,
995 TCP/UDP packet and if so, figure out ports / protocol of the 798 protocol,
996 existing session from the IP data in the ICMP payload */ 799 len,
997 source_port = 0; 800 &src_address->address.ipv4,
998 destination_port = 0; 801 &dst_address->address.ipv4);
999 switch (af)
1000 {
1001 case AF_INET:
1002 protocol = IPPROTO_ICMP;
1003 switch (icmp->type)
1004 {
1005 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1006 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1007 break;
1008 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1009 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1010 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1011 if (pktlen <
1012 sizeof (struct GNUNET_TUN_IcmpHeader) +
1013 sizeof (struct GNUNET_TUN_IPv4Header) + 8)
1014 {
1015 /* blame kernel */
1016 GNUNET_break (0);
1017 return;
1018 }
1019 ipv4 = (const struct GNUNET_TUN_IPv4Header *) &icmp[1];
1020 protocol = ipv4->protocol;
1021 /* could be TCP or UDP, but both have the ports in the right
1022 place, so that doesn't matter here */
1023 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv4[1];
1024 /* swap ports, as they are from the original message */
1025 destination_port = ntohs (udp->source_port);
1026 source_port = ntohs (udp->destination_port);
1027 /* throw away ICMP payload, won't be useful for the other side anyway */
1028 pktlen = sizeof (struct GNUNET_TUN_IcmpHeader);
1029 break;
1030 default:
1031 GNUNET_STATISTICS_update (stats,
1032 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1033 1, GNUNET_NO);
1034 return;
1035 }
1036 break;
1037 case AF_INET6:
1038 protocol = IPPROTO_ICMPV6;
1039 switch (icmp->type)
1040 {
1041 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1042 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1043 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1044 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1045 if (pktlen <
1046 sizeof (struct GNUNET_TUN_IcmpHeader) +
1047 sizeof (struct GNUNET_TUN_IPv6Header) + 8)
1048 {
1049 /* blame kernel */
1050 GNUNET_break (0);
1051 return;
1052 }
1053 ipv6 = (const struct GNUNET_TUN_IPv6Header *) &icmp[1];
1054 protocol = ipv6->next_header;
1055 /* could be TCP or UDP, but both have the ports in the right
1056 place, so that doesn't matter here */
1057 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv6[1];
1058 /* swap ports, as they are from the original message */
1059 destination_port = ntohs (udp->source_port);
1060 source_port = ntohs (udp->destination_port);
1061 /* throw away ICMP payload, won't be useful for the other side anyway */
1062 pktlen = sizeof (struct GNUNET_TUN_IcmpHeader);
1063 break;
1064 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1065 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1066 break;
1067 default:
1068 GNUNET_STATISTICS_update (stats,
1069 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1070 1, GNUNET_NO);
1071 return;
1072 }
1073 break;
1074 default:
1075 GNUNET_assert (0);
1076 }
1077 switch (protocol) 802 switch (protocol)
1078 { 803 {
1079 case IPPROTO_ICMP:
1080 state = get_redirect_state (af,
1081 IPPROTO_ICMP,
1082 source_ip,
1083 0,
1084 destination_ip,
1085 0,
1086 NULL);
1087 break;
1088 case IPPROTO_ICMPV6:
1089 state = get_redirect_state (af,
1090 IPPROTO_ICMPV6,
1091 source_ip,
1092 0,
1093 destination_ip,
1094 0,
1095 NULL);
1096 break;
1097 case IPPROTO_UDP: 804 case IPPROTO_UDP:
1098 state = get_redirect_state (af, 805 {
1099 IPPROTO_UDP, 806 struct GNUNET_TUN_UdpHeader *pkt4_udp = (struct GNUNET_TUN_UdpHeader *) &pkt4[1];
1100 source_ip, 807
1101 source_port, 808 pkt4_udp->source_port = htons (src_address->port);
1102 destination_ip, 809 pkt4_udp->destination_port = htons (dst_address->port);
1103 destination_port, 810 pkt4_udp->len = htons ((uint16_t) payload_length);
1104 NULL); 811 GNUNET_TUN_calculate_udp4_checksum (pkt4,
812 pkt4_udp,
813 payload,
814 payload_length);
815 GNUNET_memcpy (&pkt4_udp[1],
816 payload,
817 payload_length);
818 }
1105 break; 819 break;
1106 case IPPROTO_TCP: 820 case IPPROTO_TCP:
1107 state = get_redirect_state (af, 821 {
1108 IPPROTO_TCP, 822 struct GNUNET_TUN_TcpHeader *pkt4_tcp = (struct GNUNET_TUN_TcpHeader *) &pkt4[1];
1109 source_ip, 823
1110 source_port, 824 *pkt4_tcp = *tcp_header;
1111 destination_ip, 825 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1112 destination_port, 826 "Sending TCP packet from port %u to port %u\n",
1113 NULL); 827 src_address->port,
828 dst_address->port);
829 pkt4_tcp->source_port = htons (src_address->port);
830 pkt4_tcp->destination_port = htons (dst_address->port);
831 GNUNET_TUN_calculate_tcp4_checksum (pkt4,
832 pkt4_tcp,
833 payload,
834 payload_length);
835 GNUNET_memcpy (&pkt4_tcp[1],
836 payload,
837 payload_length);
838 }
1114 break; 839 break;
1115 default: 840 default:
1116 GNUNET_STATISTICS_update (stats, 841 GNUNET_assert (0);
1117 gettext_noop ("# ICMP packets dropped (not allowed)"),
1118 1,
1119 GNUNET_NO);
1120 return;
1121 }
1122 if (NULL == state)
1123 {
1124 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1125 _("ICMP Packet dropped, have no matching connection information\n"));
1126 return;
1127 } 842 }
1128 mlen = sizeof (struct GNUNET_EXIT_IcmpToVPNMessage) + pktlen - sizeof (struct GNUNET_TUN_IcmpHeader);
1129 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueue) + mlen);
1130 tnq->payload = &tnq[1];
1131 tnq->len = mlen;
1132 i2v = (struct GNUNET_EXIT_IcmpToVPNMessage *) &tnq[1];
1133 i2v->header.size = htons ((uint16_t) mlen);
1134 i2v->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN);
1135 i2v->af = htonl (af);
1136 GNUNET_memcpy (&i2v->icmp_header,
1137 icmp,
1138 pktlen);
1139 send_packet_to_cadet_channel (state, tnq);
1140} 843}
1141 844
1142 845
1143/** 846/**
1144 * @brief Handles an UDP packet received from the helper. 847 * Prepare an IPv6 packet for transmission via the TUN interface.
848 * Initializes the IP header and calculates checksums (IP+UDP/TCP).
849 * For UDP, the UDP header will be fully created, whereas for TCP
850 * only the ports and checksum will be filled in. So for TCP,
851 * a skeleton TCP header must be part of the provided payload.
1145 * 852 *
1146 * @param udp A pointer to the Packet 853 * @param payload payload of the packet (starting with UDP payload or
1147 * @param pktlen number of bytes in 'udp' 854 * TCP header, depending on protocol)
1148 * @param af address family (AFINET or AF_INET6) 855 * @param payload_length number of bytes in @a payload
1149 * @param destination_ip destination IP-address of the IP packet (should 856 * @param protocol IPPROTO_UDP or IPPROTO_TCP
1150 * be our local address) 857 * @param tcp_header skeleton TCP header data to send, NULL for UDP
1151 * @param source_ip original source IP-address of the IP packet (should 858 * @param src_address source address to use (IP and port)
1152 * be the original destination address) 859 * @param dst_address destination address to use (IP and port)
860 * @param pkt6 where to write the assembled packet; must
861 * contain enough space for the IP header, UDP/TCP header
862 * AND the payload
1153 */ 863 */
1154static void 864static void
1155udp_from_helper (const struct GNUNET_TUN_UdpHeader *udp, 865prepare_ipv6_packet (const void *payload,
1156 size_t pktlen, 866 size_t payload_length,
1157 int af, 867 int protocol,
1158 const void *destination_ip, 868 const struct GNUNET_TUN_TcpHeader *tcp_header,
1159 const void *source_ip) 869 const struct SocketAddress *src_address,
870 const struct SocketAddress *dst_address,
871 struct GNUNET_TUN_IPv6Header *pkt6)
1160{ 872{
1161 struct ChannelState *state; 873 size_t len;
1162 struct ChannelMessageQueue *tnq;
1163 struct GNUNET_EXIT_UdpReplyMessage *urm;
1164 size_t mlen;
1165 874
875 len = payload_length;
876 switch (protocol)
1166 { 877 {
1167 char sbuf[INET6_ADDRSTRLEN]; 878 case IPPROTO_UDP:
1168 char dbuf[INET6_ADDRSTRLEN]; 879 len += sizeof (struct GNUNET_TUN_UdpHeader);
1169 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 880 break;
1170 "Received UDP packet going from %s:%u to %s:%u\n", 881 case IPPROTO_TCP:
1171 inet_ntop (af, 882 len += sizeof (struct GNUNET_TUN_TcpHeader);
1172 source_ip, 883 break;
1173 sbuf, sizeof (sbuf)), 884 default:
1174 (unsigned int) ntohs (udp->source_port),
1175 inet_ntop (af,
1176 destination_ip,
1177 dbuf, sizeof (dbuf)),
1178 (unsigned int) ntohs (udp->destination_port));
1179 }
1180 if (pktlen < sizeof (struct GNUNET_TUN_UdpHeader))
1181 {
1182 /* blame kernel */
1183 GNUNET_break (0); 885 GNUNET_break (0);
1184 return; 886 return;
1185 } 887 }
1186 if (pktlen != ntohs (udp->len)) 888 if (len > UINT16_MAX)
1187 { 889 {
1188 /* blame kernel */
1189 GNUNET_break (0); 890 GNUNET_break (0);
1190 return; 891 return;
1191 } 892 }
1192 state = get_redirect_state (af, 893
1193 IPPROTO_UDP, 894 GNUNET_TUN_initialize_ipv6_header (pkt6,
1194 source_ip, 895 protocol,
1195 ntohs (udp->source_port), 896 len,
1196 destination_ip, 897 &src_address->address.ipv6,
1197 ntohs (udp->destination_port), 898 &dst_address->address.ipv6);
1198 NULL); 899
1199 if (NULL == state) 900 switch (protocol)
1200 { 901 {
1201 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 902 case IPPROTO_UDP:
1202 _("UDP Packet dropped, have no matching connection information\n")); 903 {
1203 return; 904 struct GNUNET_TUN_UdpHeader *pkt6_udp = (struct GNUNET_TUN_UdpHeader *) &pkt6[1];
905
906 pkt6_udp->source_port = htons (src_address->port);
907 pkt6_udp->destination_port = htons (dst_address->port);
908 pkt6_udp->len = htons ((uint16_t) payload_length);
909 GNUNET_TUN_calculate_udp6_checksum (pkt6,
910 pkt6_udp,
911 payload,
912 payload_length);
913 GNUNET_memcpy (&pkt6_udp[1],
914 payload,
915 payload_length);
916 }
917 break;
918 case IPPROTO_TCP:
919 {
920 struct GNUNET_TUN_TcpHeader *pkt6_tcp = (struct GNUNET_TUN_TcpHeader *) &pkt6[1];
921
922 /* GNUNET_memcpy first here as some TCP header fields are initialized this way! */
923 *pkt6_tcp = *tcp_header;
924 pkt6_tcp->source_port = htons (src_address->port);
925 pkt6_tcp->destination_port = htons (dst_address->port);
926 GNUNET_TUN_calculate_tcp6_checksum (pkt6,
927 pkt6_tcp,
928 payload,
929 payload_length);
930 GNUNET_memcpy (&pkt6_tcp[1],
931 payload,
932 payload_length);
933 }
934 break;
935 default:
936 GNUNET_assert (0);
937 break;
1204 } 938 }
1205 mlen = sizeof (struct GNUNET_EXIT_UdpReplyMessage) + pktlen - sizeof (struct GNUNET_TUN_UdpHeader);
1206 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueue) + mlen);
1207 tnq->payload = &tnq[1];
1208 tnq->len = mlen;
1209 urm = (struct GNUNET_EXIT_UdpReplyMessage *) &tnq[1];
1210 urm->header.size = htons ((uint16_t) mlen);
1211 urm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY);
1212 urm->source_port = htons (0);
1213 urm->destination_port = htons (0);
1214 GNUNET_memcpy (&urm[1],
1215 &udp[1],
1216 pktlen - sizeof (struct GNUNET_TUN_UdpHeader));
1217 send_packet_to_cadet_channel (state, tnq);
1218} 939}
1219 940
1220 941
1221/** 942/**
1222 * @brief Handles a TCP packet received from the helper. 943 * Send a TCP packet via the TUN interface.
1223 * 944 *
1224 * @param tcp A pointer to the Packet 945 * @param destination_address IP and port to use for the TCP packet's destination
1225 * @param pktlen the length of the packet, including its TCP header 946 * @param source_address IP and port to use for the TCP packet's source
1226 * @param af address family (AFINET or AF_INET6) 947 * @param tcp_header header template to use
1227 * @param destination_ip destination IP-address of the IP packet (should 948 * @param payload payload of the TCP packet
1228 * be our local address) 949 * @param payload_length number of bytes in @a payload
1229 * @param source_ip original source IP-address of the IP packet (should
1230 * be the original destination address)
1231 */ 950 */
1232static void 951static void
1233tcp_from_helper (const struct GNUNET_TUN_TcpHeader *tcp, 952send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
1234 size_t pktlen, 953 const struct SocketAddress *source_address,
1235 int af, 954 const struct GNUNET_TUN_TcpHeader *tcp_header,
1236 const void *destination_ip, 955 const void *payload,
1237 const void *source_ip) 956 size_t payload_length)
1238{ 957{
1239 struct ChannelState *state; 958 size_t len;
1240 char buf[pktlen] GNUNET_ALIGN;
1241 struct GNUNET_TUN_TcpHeader *mtcp;
1242 struct GNUNET_EXIT_TcpDataMessage *tdm;
1243 struct ChannelMessageQueue *tnq;
1244 size_t mlen;
1245 959
960 GNUNET_STATISTICS_update (stats,
961 gettext_noop ("# TCP packets sent via TUN"),
962 1,
963 GNUNET_NO);
964 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
965 "Sending packet with %u bytes TCP payload via TUN\n",
966 (unsigned int) payload_length);
967 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
968 switch (source_address->af)
1246 { 969 {
1247 char sbuf[INET6_ADDRSTRLEN]; 970 case AF_INET:
1248 char dbuf[INET6_ADDRSTRLEN]; 971 len += sizeof (struct GNUNET_TUN_IPv4Header);
1249 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 972 break;
1250 "Received TCP packet with %u bytes going from %s:%u to %s:%u\n", 973 case AF_INET6:
1251 (unsigned int) (pktlen - sizeof (struct GNUNET_TUN_TcpHeader)), 974 len += sizeof (struct GNUNET_TUN_IPv6Header);
1252 inet_ntop (af, 975 break;
1253 source_ip, 976 default:
1254 sbuf, sizeof (sbuf)), 977 GNUNET_break (0);
1255 (unsigned int) ntohs (tcp->source_port), 978 return;
1256 inet_ntop (af,
1257 destination_ip,
1258 dbuf, sizeof (dbuf)),
1259 (unsigned int) ntohs (tcp->destination_port));
1260 } 979 }
1261 if (pktlen < sizeof (struct GNUNET_TUN_TcpHeader)) 980 len += sizeof (struct GNUNET_TUN_TcpHeader);
981 len += payload_length;
982 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1262 { 983 {
1263 /* blame kernel */
1264 GNUNET_break (0); 984 GNUNET_break (0);
1265 return; 985 return;
1266 } 986 }
1267 state = get_redirect_state (af,
1268 IPPROTO_TCP,
1269 source_ip,
1270 ntohs (tcp->source_port),
1271 destination_ip,
1272 ntohs (tcp->destination_port),
1273 NULL);
1274 if (NULL == state)
1275 { 987 {
1276 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 988 char buf[len] GNUNET_ALIGN;
1277 _("TCP Packet dropped, have no matching connection information\n")); 989 struct GNUNET_MessageHeader *hdr;
990 struct GNUNET_TUN_Layer2PacketHeader *tun;
1278 991
1279 return; 992 hdr = (struct GNUNET_MessageHeader *) buf;
1280 } 993 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1281 /* mug port numbers and crc to avoid information leakage; 994 hdr->size = htons (len);
1282 sender will need to lookup the correct values anyway */ 995 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1283 GNUNET_memcpy (buf, tcp, pktlen); 996 tun->flags = htons (0);
1284 mtcp = (struct GNUNET_TUN_TcpHeader *) buf; 997 switch (source_address->af)
1285 mtcp->source_port = 0; 998 {
1286 mtcp->destination_port = 0; 999 case AF_INET:
1287 mtcp->crc = 0; 1000 {
1001 struct GNUNET_TUN_IPv4Header *ipv4
1002 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
1288 1003
1289 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) + (pktlen - sizeof (struct GNUNET_TUN_TcpHeader)); 1004 tun->proto = htons (ETH_P_IPV4);
1290 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE) 1005 prepare_ipv4_packet (payload,
1291 { 1006 payload_length,
1292 GNUNET_break (0); 1007 IPPROTO_TCP,
1293 return; 1008 tcp_header,
1294 } 1009 source_address,
1010 destination_address,
1011 ipv4);
1012 }
1013 break;
1014 case AF_INET6:
1015 {
1016 struct GNUNET_TUN_IPv6Header *ipv6
1017 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1295 1018
1296 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueue) + mlen); 1019 tun->proto = htons (ETH_P_IPV6);
1297 tnq->payload = &tnq[1]; 1020 prepare_ipv6_packet (payload,
1298 tnq->len = mlen; 1021 payload_length,
1299 tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1]; 1022 IPPROTO_TCP,
1300 tdm->header.size = htons ((uint16_t) mlen); 1023 tcp_header,
1301 tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN); 1024 source_address,
1302 tdm->reserved = htonl (0); 1025 destination_address,
1303 GNUNET_memcpy (&tdm->tcp_header, 1026 ipv6);
1304 buf, 1027 }
1305 pktlen); 1028 break;
1306 send_packet_to_cadet_channel (state, tnq); 1029 default:
1030 GNUNET_assert (0);
1031 break;
1032 }
1033 if (NULL != helper_handle)
1034 (void) GNUNET_HELPER_send (helper_handle,
1035 (const struct GNUNET_MessageHeader*) buf,
1036 GNUNET_YES,
1037 NULL,
1038 NULL);
1039 }
1307} 1040}
1308 1041
1309 1042
1310/** 1043/**
1311 * Receive packets from the helper-process 1044 * Send an ICMP packet via the TUN interface.
1312 * 1045 *
1313 * @param cls unused 1046 * @param destination_address IP to use for the ICMP packet's destination
1314 * @param client unsued 1047 * @param source_address IP to use for the ICMP packet's source
1315 * @param message message received from helper 1048 * @param icmp_header ICMP header to send
1049 * @param payload payload of the ICMP packet (does NOT include ICMP header)
1050 * @param payload_length number of bytes of data in @a payload
1316 */ 1051 */
1317static int 1052static void
1318message_token (void *cls GNUNET_UNUSED, 1053send_icmp_packet_via_tun (const struct SocketAddress *destination_address,
1319 void *client GNUNET_UNUSED, 1054 const struct SocketAddress *source_address,
1320 const struct GNUNET_MessageHeader *message) 1055 const struct GNUNET_TUN_IcmpHeader *icmp_header,
1056 const void *payload, size_t payload_length)
1321{ 1057{
1322 const struct GNUNET_TUN_Layer2PacketHeader *pkt_tun; 1058 size_t len;
1323 size_t size; 1059 struct GNUNET_TUN_IcmpHeader *icmp;
1324 1060
1325 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1326 "Got %u-byte message of type %u from gnunet-helper-exit\n",
1327 ntohs (message->size),
1328 ntohs (message->type));
1329 GNUNET_STATISTICS_update (stats, 1061 GNUNET_STATISTICS_update (stats,
1330 gettext_noop ("# Packets received from TUN"), 1062 gettext_noop ("# ICMP packets sent via TUN"),
1331 1, GNUNET_NO); 1063 1, GNUNET_NO);
1332 if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) 1064 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1065 "Sending packet with %u bytes ICMP payload via TUN\n",
1066 (unsigned int) payload_length);
1067 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
1068 switch (destination_address->af)
1333 { 1069 {
1070 case AF_INET:
1071 len += sizeof (struct GNUNET_TUN_IPv4Header);
1072 break;
1073 case AF_INET6:
1074 len += sizeof (struct GNUNET_TUN_IPv6Header);
1075 break;
1076 default:
1334 GNUNET_break (0); 1077 GNUNET_break (0);
1335 return GNUNET_OK; 1078 return;
1336 } 1079 }
1337 size = ntohs (message->size); 1080 len += sizeof (struct GNUNET_TUN_IcmpHeader);
1338 if (size < sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_MessageHeader)) 1081 len += payload_length;
1082 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1339 { 1083 {
1340 GNUNET_break (0); 1084 GNUNET_break (0);
1341 return GNUNET_OK; 1085 return;
1342 } 1086 }
1343 GNUNET_STATISTICS_update (stats,
1344 gettext_noop ("# Bytes received from TUN"),
1345 size, GNUNET_NO);
1346 pkt_tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1347 size -= sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_MessageHeader);
1348 switch (ntohs (pkt_tun->proto))
1349 { 1087 {
1350 case ETH_P_IPV4: 1088 char buf[len] GNUNET_ALIGN;
1351 { 1089 struct GNUNET_MessageHeader *hdr;
1352 const struct GNUNET_TUN_IPv4Header *pkt4; 1090 struct GNUNET_TUN_Layer2PacketHeader *tun;
1353
1354 if (size < sizeof (struct GNUNET_TUN_IPv4Header))
1355 {
1356 /* Kernel to blame? */
1357 GNUNET_break (0);
1358 return GNUNET_OK;
1359 }
1360 pkt4 = (const struct GNUNET_TUN_IPv4Header *) &pkt_tun[1];
1361 if (size != ntohs (pkt4->total_length))
1362 {
1363 /* Kernel to blame? */
1364 GNUNET_break (0);
1365 return GNUNET_OK;
1366 }
1367 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
1368 {
1369 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1370 _("IPv4 packet options received. Ignored.\n"));
1371 return GNUNET_OK;
1372 }
1373 1091
1374 size -= sizeof (struct GNUNET_TUN_IPv4Header); 1092 hdr= (struct GNUNET_MessageHeader *) buf;
1375 switch (pkt4->protocol) 1093 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1376 { 1094 hdr->size = htons (len);
1377 case IPPROTO_UDP: 1095 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1378 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt4[1], size, 1096 tun->flags = htons (0);
1379 AF_INET, 1097 switch (source_address->af)
1380 &pkt4->destination_address,
1381 &pkt4->source_address);
1382 break;
1383 case IPPROTO_TCP:
1384 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt4[1], size,
1385 AF_INET,
1386 &pkt4->destination_address,
1387 &pkt4->source_address);
1388 break;
1389 case IPPROTO_ICMP:
1390 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt4[1], size,
1391 AF_INET,
1392 &pkt4->destination_address,
1393 &pkt4->source_address);
1394 break;
1395 default:
1396 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1397 _("IPv4 packet with unsupported next header %u received. Ignored.\n"),
1398 (int) pkt4->protocol);
1399 return GNUNET_OK;
1400 }
1401 }
1402 break;
1403 case ETH_P_IPV6:
1404 { 1098 {
1405 const struct GNUNET_TUN_IPv6Header *pkt6; 1099 case AF_INET:
1406
1407 if (size < sizeof (struct GNUNET_TUN_IPv6Header))
1408 {
1409 /* Kernel to blame? */
1410 GNUNET_break (0);
1411 return GNUNET_OK;
1412 }
1413 pkt6 = (struct GNUNET_TUN_IPv6Header *) &pkt_tun[1];
1414 if (size != ntohs (pkt6->payload_length) + sizeof (struct GNUNET_TUN_IPv6Header))
1415 { 1100 {
1416 /* Kernel to blame? */ 1101 struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
1417 GNUNET_break (0); 1102
1418 return GNUNET_OK; 1103 tun->proto = htons (ETH_P_IPV4);
1104 GNUNET_TUN_initialize_ipv4_header (ipv4,
1105 IPPROTO_ICMP,
1106 sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length,
1107 &source_address->address.ipv4,
1108 &destination_address->address.ipv4);
1109 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv4[1];
1419 } 1110 }
1420 size -= sizeof (struct GNUNET_TUN_IPv6Header); 1111 break;
1421 switch (pkt6->next_header) 1112 case AF_INET6:
1422 { 1113 {
1423 case IPPROTO_UDP: 1114 struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1424 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt6[1], size, 1115
1425 AF_INET6, 1116 tun->proto = htons (ETH_P_IPV6);
1426 &pkt6->destination_address, 1117 GNUNET_TUN_initialize_ipv6_header (ipv6,
1427 &pkt6->source_address); 1118 IPPROTO_ICMPV6,
1428 break; 1119 sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length,
1429 case IPPROTO_TCP: 1120 &source_address->address.ipv6,
1430 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt6[1], size, 1121 &destination_address->address.ipv6);
1431 AF_INET6, 1122 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv6[1];
1432 &pkt6->destination_address,
1433 &pkt6->source_address);
1434 break;
1435 case IPPROTO_ICMPV6:
1436 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt6[1], size,
1437 AF_INET6,
1438 &pkt6->destination_address,
1439 &pkt6->source_address);
1440 break;
1441 default:
1442 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1443 _("IPv6 packet with unsupported next header %d received. Ignored.\n"),
1444 pkt6->next_header);
1445 return GNUNET_OK;
1446 } 1123 }
1124 break;
1125 default:
1126 GNUNET_assert (0);
1127 break;
1447 } 1128 }
1448 break; 1129 *icmp = *icmp_header;
1449 default: 1130 GNUNET_memcpy (&icmp[1],
1450 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1131 payload,
1451 _("Packet from unknown protocol %u received. Ignored.\n"), 1132 payload_length);
1452 ntohs (pkt_tun->proto)); 1133 GNUNET_TUN_calculate_icmp_checksum (icmp,
1453 break; 1134 payload,
1135 payload_length);
1136 if (NULL != helper_handle)
1137 (void) GNUNET_HELPER_send (helper_handle,
1138 (const struct GNUNET_MessageHeader*) buf,
1139 GNUNET_YES,
1140 NULL, NULL);
1454 } 1141 }
1455 return GNUNET_OK;
1456} 1142}
1457 1143
1458 1144
@@ -1637,223 +1323,25 @@ setup_state_record (struct ChannelState *state)
1637 1323
1638 1324
1639/** 1325/**
1640 * Prepare an IPv4 packet for transmission via the TUN interface. 1326 * Send a UDP packet via the TUN interface.
1641 * Initializes the IP header and calculates checksums (IP+UDP/TCP).
1642 * For UDP, the UDP header will be fully created, whereas for TCP
1643 * only the ports and checksum will be filled in. So for TCP,
1644 * a skeleton TCP header must be part of the provided payload.
1645 *
1646 * @param payload payload of the packet (starting with UDP payload or
1647 * TCP header, depending on protocol)
1648 * @param payload_length number of bytes in @a payload
1649 * @param protocol IPPROTO_UDP or IPPROTO_TCP
1650 * @param tcp_header skeleton of the TCP header, NULL for UDP
1651 * @param src_address source address to use (IP and port)
1652 * @param dst_address destination address to use (IP and port)
1653 * @param pkt4 where to write the assembled packet; must
1654 * contain enough space for the IP header, UDP/TCP header
1655 * AND the payload
1656 */
1657static void
1658prepare_ipv4_packet (const void *payload,
1659 size_t payload_length,
1660 int protocol,
1661 const struct GNUNET_TUN_TcpHeader *tcp_header,
1662 const struct SocketAddress *src_address,
1663 const struct SocketAddress *dst_address,
1664 struct GNUNET_TUN_IPv4Header *pkt4)
1665{
1666 size_t len;
1667
1668 len = payload_length;
1669 switch (protocol)
1670 {
1671 case IPPROTO_UDP:
1672 len += sizeof (struct GNUNET_TUN_UdpHeader);
1673 break;
1674 case IPPROTO_TCP:
1675 len += sizeof (struct GNUNET_TUN_TcpHeader);
1676 GNUNET_assert (NULL != tcp_header);
1677 break;
1678 default:
1679 GNUNET_break (0);
1680 return;
1681 }
1682 if (len + sizeof (struct GNUNET_TUN_IPv4Header) > UINT16_MAX)
1683 {
1684 GNUNET_break (0);
1685 return;
1686 }
1687
1688 GNUNET_TUN_initialize_ipv4_header (pkt4,
1689 protocol,
1690 len,
1691 &src_address->address.ipv4,
1692 &dst_address->address.ipv4);
1693 switch (protocol)
1694 {
1695 case IPPROTO_UDP:
1696 {
1697 struct GNUNET_TUN_UdpHeader *pkt4_udp = (struct GNUNET_TUN_UdpHeader *) &pkt4[1];
1698
1699 pkt4_udp->source_port = htons (src_address->port);
1700 pkt4_udp->destination_port = htons (dst_address->port);
1701 pkt4_udp->len = htons ((uint16_t) payload_length);
1702 GNUNET_TUN_calculate_udp4_checksum (pkt4,
1703 pkt4_udp,
1704 payload,
1705 payload_length);
1706 GNUNET_memcpy (&pkt4_udp[1],
1707 payload,
1708 payload_length);
1709 }
1710 break;
1711 case IPPROTO_TCP:
1712 {
1713 struct GNUNET_TUN_TcpHeader *pkt4_tcp = (struct GNUNET_TUN_TcpHeader *) &pkt4[1];
1714
1715 *pkt4_tcp = *tcp_header;
1716 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1717 "Sending TCP packet from port %u to port %u\n",
1718 src_address->port,
1719 dst_address->port);
1720 pkt4_tcp->source_port = htons (src_address->port);
1721 pkt4_tcp->destination_port = htons (dst_address->port);
1722 GNUNET_TUN_calculate_tcp4_checksum (pkt4,
1723 pkt4_tcp,
1724 payload,
1725 payload_length);
1726 GNUNET_memcpy (&pkt4_tcp[1],
1727 payload,
1728 payload_length);
1729 }
1730 break;
1731 default:
1732 GNUNET_assert (0);
1733 }
1734}
1735
1736
1737/**
1738 * Prepare an IPv6 packet for transmission via the TUN interface.
1739 * Initializes the IP header and calculates checksums (IP+UDP/TCP).
1740 * For UDP, the UDP header will be fully created, whereas for TCP
1741 * only the ports and checksum will be filled in. So for TCP,
1742 * a skeleton TCP header must be part of the provided payload.
1743 *
1744 * @param payload payload of the packet (starting with UDP payload or
1745 * TCP header, depending on protocol)
1746 * @param payload_length number of bytes in @a payload
1747 * @param protocol IPPROTO_UDP or IPPROTO_TCP
1748 * @param tcp_header skeleton TCP header data to send, NULL for UDP
1749 * @param src_address source address to use (IP and port)
1750 * @param dst_address destination address to use (IP and port)
1751 * @param pkt6 where to write the assembled packet; must
1752 * contain enough space for the IP header, UDP/TCP header
1753 * AND the payload
1754 */
1755static void
1756prepare_ipv6_packet (const void *payload,
1757 size_t payload_length,
1758 int protocol,
1759 const struct GNUNET_TUN_TcpHeader *tcp_header,
1760 const struct SocketAddress *src_address,
1761 const struct SocketAddress *dst_address,
1762 struct GNUNET_TUN_IPv6Header *pkt6)
1763{
1764 size_t len;
1765
1766 len = payload_length;
1767 switch (protocol)
1768 {
1769 case IPPROTO_UDP:
1770 len += sizeof (struct GNUNET_TUN_UdpHeader);
1771 break;
1772 case IPPROTO_TCP:
1773 len += sizeof (struct GNUNET_TUN_TcpHeader);
1774 break;
1775 default:
1776 GNUNET_break (0);
1777 return;
1778 }
1779 if (len > UINT16_MAX)
1780 {
1781 GNUNET_break (0);
1782 return;
1783 }
1784
1785 GNUNET_TUN_initialize_ipv6_header (pkt6,
1786 protocol,
1787 len,
1788 &src_address->address.ipv6,
1789 &dst_address->address.ipv6);
1790
1791 switch (protocol)
1792 {
1793 case IPPROTO_UDP:
1794 {
1795 struct GNUNET_TUN_UdpHeader *pkt6_udp = (struct GNUNET_TUN_UdpHeader *) &pkt6[1];
1796
1797 pkt6_udp->source_port = htons (src_address->port);
1798 pkt6_udp->destination_port = htons (dst_address->port);
1799 pkt6_udp->len = htons ((uint16_t) payload_length);
1800 GNUNET_TUN_calculate_udp6_checksum (pkt6,
1801 pkt6_udp,
1802 payload,
1803 payload_length);
1804 GNUNET_memcpy (&pkt6_udp[1],
1805 payload,
1806 payload_length);
1807 }
1808 break;
1809 case IPPROTO_TCP:
1810 {
1811 struct GNUNET_TUN_TcpHeader *pkt6_tcp = (struct GNUNET_TUN_TcpHeader *) &pkt6[1];
1812
1813 /* GNUNET_memcpy first here as some TCP header fields are initialized this way! */
1814 *pkt6_tcp = *tcp_header;
1815 pkt6_tcp->source_port = htons (src_address->port);
1816 pkt6_tcp->destination_port = htons (dst_address->port);
1817 GNUNET_TUN_calculate_tcp6_checksum (pkt6,
1818 pkt6_tcp,
1819 payload,
1820 payload_length);
1821 GNUNET_memcpy (&pkt6_tcp[1],
1822 payload,
1823 payload_length);
1824 }
1825 break;
1826 default:
1827 GNUNET_assert (0);
1828 break;
1829 }
1830}
1831
1832
1833/**
1834 * Send a TCP packet via the TUN interface.
1835 * 1327 *
1836 * @param destination_address IP and port to use for the TCP packet's destination 1328 * @param destination_address IP and port to use for the UDP packet's destination
1837 * @param source_address IP and port to use for the TCP packet's source 1329 * @param source_address IP and port to use for the UDP packet's source
1838 * @param tcp_header header template to use 1330 * @param payload payload of the UDP packet (does NOT include UDP header)
1839 * @param payload payload of the TCP packet 1331 * @param payload_length number of bytes of data in @a payload
1840 * @param payload_length number of bytes in @a payload
1841 */ 1332 */
1842static void 1333static void
1843send_tcp_packet_via_tun (const struct SocketAddress *destination_address, 1334send_udp_packet_via_tun (const struct SocketAddress *destination_address,
1844 const struct SocketAddress *source_address, 1335 const struct SocketAddress *source_address,
1845 const struct GNUNET_TUN_TcpHeader *tcp_header, 1336 const void *payload, size_t payload_length)
1846 const void *payload,
1847 size_t payload_length)
1848{ 1337{
1849 size_t len; 1338 size_t len;
1850 1339
1851 GNUNET_STATISTICS_update (stats, 1340 GNUNET_STATISTICS_update (stats,
1852 gettext_noop ("# TCP packets sent via TUN"), 1341 gettext_noop ("# UDP packets sent via TUN"),
1853 1, 1342 1, GNUNET_NO);
1854 GNUNET_NO);
1855 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1343 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1856 "Sending packet with %u bytes TCP payload via TUN\n", 1344 "Sending packet with %u bytes UDP payload via TUN\n",
1857 (unsigned int) payload_length); 1345 (unsigned int) payload_length);
1858 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader); 1346 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
1859 switch (source_address->af) 1347 switch (source_address->af)
@@ -1868,7 +1356,7 @@ send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
1868 GNUNET_break (0); 1356 GNUNET_break (0);
1869 return; 1357 return;
1870 } 1358 }
1871 len += sizeof (struct GNUNET_TUN_TcpHeader); 1359 len += sizeof (struct GNUNET_TUN_UdpHeader);
1872 len += payload_length; 1360 len += payload_length;
1873 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE) 1361 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1874 { 1362 {
@@ -1880,7 +1368,7 @@ send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
1880 struct GNUNET_MessageHeader *hdr; 1368 struct GNUNET_MessageHeader *hdr;
1881 struct GNUNET_TUN_Layer2PacketHeader *tun; 1369 struct GNUNET_TUN_Layer2PacketHeader *tun;
1882 1370
1883 hdr = (struct GNUNET_MessageHeader *) buf; 1371 hdr= (struct GNUNET_MessageHeader *) buf;
1884 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); 1372 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1885 hdr->size = htons (len); 1373 hdr->size = htons (len);
1886 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1]; 1374 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
@@ -1889,14 +1377,13 @@ send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
1889 { 1377 {
1890 case AF_INET: 1378 case AF_INET:
1891 { 1379 {
1892 struct GNUNET_TUN_IPv4Header *ipv4 1380 struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
1893 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
1894 1381
1895 tun->proto = htons (ETH_P_IPV4); 1382 tun->proto = htons (ETH_P_IPV4);
1896 prepare_ipv4_packet (payload, 1383 prepare_ipv4_packet (payload,
1897 payload_length, 1384 payload_length,
1898 IPPROTO_TCP, 1385 IPPROTO_UDP,
1899 tcp_header, 1386 NULL,
1900 source_address, 1387 source_address,
1901 destination_address, 1388 destination_address,
1902 ipv4); 1389 ipv4);
@@ -1904,14 +1391,13 @@ send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
1904 break; 1391 break;
1905 case AF_INET6: 1392 case AF_INET6:
1906 { 1393 {
1907 struct GNUNET_TUN_IPv6Header *ipv6 1394 struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1908 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1909 1395
1910 tun->proto = htons (ETH_P_IPV6); 1396 tun->proto = htons (ETH_P_IPV6);
1911 prepare_ipv6_packet (payload, 1397 prepare_ipv6_packet (payload,
1912 payload_length, 1398 payload_length,
1913 IPPROTO_TCP, 1399 IPPROTO_UDP,
1914 tcp_header, 1400 NULL,
1915 source_address, 1401 source_address,
1916 destination_address, 1402 destination_address,
1917 ipv6); 1403 ipv6);
@@ -1925,48 +1411,202 @@ send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
1925 (void) GNUNET_HELPER_send (helper_handle, 1411 (void) GNUNET_HELPER_send (helper_handle,
1926 (const struct GNUNET_MessageHeader*) buf, 1412 (const struct GNUNET_MessageHeader*) buf,
1927 GNUNET_YES, 1413 GNUNET_YES,
1928 NULL, 1414 NULL, NULL);
1929 NULL);
1930 } 1415 }
1931} 1416}
1932 1417
1933 1418
1934/** 1419/**
1935 * Process a request via cadet to send a request to a TCP service 1420 * Check a request to forward UDP data to the Internet via this peer.
1936 * offered by this system.
1937 * 1421 *
1938 * @param cls closure, NULL 1422 * @param cls our `struct ChannelState *`
1939 * @param channel connection to the other end 1423 * @param msg the actual message
1940 * @param channel_ctx pointer to our `struct ChannelState *`
1941 * @param message the actual message
1942 * @return #GNUNET_OK to keep the connection open, 1424 * @return #GNUNET_OK to keep the connection open,
1943 * #GNUNET_SYSERR to close it (signal serious error) 1425 * #GNUNET_SYSERR to close it (signal serious error)
1944 */ 1426 */
1945static int 1427static int
1946receive_tcp_service (void *cls, 1428check_udp_remote (void *cls,
1947 struct GNUNET_CADET_Channel *channel, 1429 const struct GNUNET_EXIT_UdpInternetMessage *msg)
1948 void **channel_ctx,
1949 const struct GNUNET_MessageHeader *message)
1950{ 1430{
1951 struct ChannelState *state = *channel_ctx; 1431 struct ChannelState *state = cls;
1952 const struct GNUNET_EXIT_TcpServiceStartMessage *start;
1953 uint16_t pkt_len = ntohs (message->size);
1954 1432
1955 if (NULL == state) 1433 if (GNUNET_YES == state->is_dns)
1956 { 1434 {
1957 GNUNET_break_op (0); 1435 GNUNET_break_op (0);
1958 return GNUNET_SYSERR; 1436 return GNUNET_SYSERR;
1959 } 1437 }
1960 if (GNUNET_YES == state->is_dns) 1438 return GNUNET_OK;
1439}
1440
1441
1442/**
1443 * Process a request to forward UDP data to the Internet via this peer.
1444 *
1445 * @param cls our `struct ChannelState *`
1446 * @param msg the actual message
1447 */
1448static void
1449handle_udp_remote (void *cls,
1450 const struct GNUNET_EXIT_UdpInternetMessage *msg)
1451{
1452 struct ChannelState *state = cls;
1453 uint16_t pkt_len = ntohs (msg->header.size) - sizeof (struct GNUNET_EXIT_UdpInternetMessage);
1454 const struct in_addr *v4;
1455 const struct in6_addr *v6;
1456 const void *payload;
1457 int af;
1458
1459 if (GNUNET_SYSERR == state->is_dns)
1460 {
1461 /* channel is UDP/TCP from now on */
1462 state->is_dns = GNUNET_NO;
1463 }
1464 GNUNET_STATISTICS_update (stats,
1465 gettext_noop ("# Bytes received from CADET"),
1466 pkt_len, GNUNET_NO);
1467 GNUNET_STATISTICS_update (stats,
1468 gettext_noop ("# UDP IP-exit requests received via cadet"),
1469 1, GNUNET_NO);
1470 af = (int) ntohl (msg->af);
1471 state->specifics.tcp_udp.ri.remote_address.af = af;
1472 switch (af)
1961 { 1473 {
1474 case AF_INET:
1475 if (pkt_len < sizeof (struct in_addr))
1476 {
1477 GNUNET_break_op (0);
1478 return;
1479 }
1480 if (! ipv4_exit)
1481 {
1482 GNUNET_break_op (0);
1483 return;
1484 }
1485 v4 = (const struct in_addr*) &msg[1];
1486 payload = &v4[1];
1487 pkt_len -= sizeof (struct in_addr);
1488 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
1489 break;
1490 case AF_INET6:
1491 if (pkt_len < sizeof (struct in6_addr))
1492 {
1493 GNUNET_break_op (0);
1494 return;
1495 }
1496 if (! ipv6_exit)
1497 {
1498 GNUNET_break_op (0);
1499 return;
1500 }
1501 v6 = (const struct in6_addr*) &msg[1];
1502 payload = &v6[1];
1503 pkt_len -= sizeof (struct in6_addr);
1504 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
1505 break;
1506 default:
1962 GNUNET_break_op (0); 1507 GNUNET_break_op (0);
1963 return GNUNET_SYSERR; 1508 return;
1964 } 1509 }
1510 {
1511 char buf[INET6_ADDRSTRLEN];
1512 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1513 "Received data from %s for forwarding to UDP %s:%u\n",
1514 GNUNET_i2s (&state->peer),
1515 inet_ntop (af,
1516 &state->specifics.tcp_udp.ri.remote_address.address,
1517 buf, sizeof (buf)),
1518 (unsigned int) ntohs (msg->destination_port));
1519 }
1520 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_UDP;
1521 state->specifics.tcp_udp.ri.remote_address.port = msg->destination_port;
1522 if (NULL == state->specifics.tcp_udp.heap_node)
1523 setup_state_record (state);
1524 if (0 != ntohs (msg->source_port))
1525 state->specifics.tcp_udp.ri.local_address.port = msg->source_port;
1526 send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1527 &state->specifics.tcp_udp.ri.local_address,
1528 payload,
1529 pkt_len);
1530 GNUNET_CADET_receive_done (state->channel);
1531}
1532
1533
1534/**
1535 * Check a request via cadet to send a request to a UDP service
1536 * offered by this system.
1537 *
1538 * @param cls our `struct ChannelState *`
1539 * @param msg the actual message
1540 * @return #GNUNET_OK to keep the connection open,
1541 * #GNUNET_SYSERR to close it (signal serious error)
1542 */
1543static int
1544check_udp_service (void *cls,
1545 const struct GNUNET_EXIT_UdpServiceMessage *msg)
1546{
1547 struct ChannelState *state = cls;
1548
1965 if (NULL == state->specifics.tcp_udp.serv) 1549 if (NULL == state->specifics.tcp_udp.serv)
1966 { 1550 {
1967 GNUNET_break_op (0); 1551 GNUNET_break_op (0);
1968 return GNUNET_SYSERR; 1552 return GNUNET_SYSERR;
1969 } 1553 }
1554 return GNUNET_OK;
1555}
1556
1557
1558/**
1559 * Process a request via cadet to send a request to a UDP service
1560 * offered by this system.
1561 *
1562 * @param cls our `struct ChannelState *`
1563 * @param msg the actual message
1564 */
1565static void
1566handle_udp_service (void *cls,
1567 const struct GNUNET_EXIT_UdpServiceMessage *msg)
1568{
1569 struct ChannelState *state = cls;
1570 uint16_t pkt_len = ntohs (msg->header.size) - sizeof (struct GNUNET_EXIT_UdpServiceMessage);
1571
1572 GNUNET_STATISTICS_update (stats,
1573 gettext_noop ("# Bytes received from CADET"),
1574 pkt_len, GNUNET_NO);
1575 GNUNET_STATISTICS_update (stats,
1576 gettext_noop ("# UDP service requests received via cadet"),
1577 1, GNUNET_NO);
1578 LOG (GNUNET_ERROR_TYPE_DEBUG,
1579 "Received data from %s for forwarding to UDP service %s on port %u\n",
1580 GNUNET_i2s (&state->peer),
1581 GNUNET_h2s (&state->specifics.tcp_udp.serv->descriptor),
1582 (unsigned int) ntohs (msg->destination_port));
1583 setup_state_record (state);
1584 if (0 != ntohs (msg->source_port))
1585 state->specifics.tcp_udp.ri.local_address.port = msg->source_port;
1586 send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1587 &state->specifics.tcp_udp.ri.local_address,
1588 &msg[1],
1589 pkt_len);
1590 GNUNET_CADET_receive_done (state->channel);
1591}
1592
1593
1594/**
1595 * Process a request via cadet to send a request to a TCP service
1596 * offered by this system.
1597 *
1598 * @param cls our `struct ChannelState *`
1599 * @param start the actual message
1600 * @return #GNUNET_OK to keep the connection open,
1601 * #GNUNET_SYSERR to close it (signal serious error)
1602 */
1603static void
1604handle_tcp_service (void *cls,
1605 const struct GNUNET_EXIT_TcpServiceStartMessage *start)
1606{
1607 struct ChannelState *state = cls;
1608 uint16_t pkt_len = ntohs (start->header.size) - sizeof (struct GNUNET_EXIT_TcpServiceStartMessage);
1609
1970 if (GNUNET_SYSERR == state->is_dns) 1610 if (GNUNET_SYSERR == state->is_dns)
1971 { 1611 {
1972 /* channel is UDP/TCP from now on */ 1612 /* channel is UDP/TCP from now on */
@@ -1980,24 +1620,6 @@ receive_tcp_service (void *cls,
1980 gettext_noop ("# Bytes received from CADET"), 1620 gettext_noop ("# Bytes received from CADET"),
1981 pkt_len, 1621 pkt_len,
1982 GNUNET_NO); 1622 GNUNET_NO);
1983 /* check that we got at least a valid header */
1984 if (pkt_len < sizeof (struct GNUNET_EXIT_TcpServiceStartMessage))
1985 {
1986 GNUNET_break_op (0);
1987 return GNUNET_SYSERR;
1988 }
1989 start = (const struct GNUNET_EXIT_TcpServiceStartMessage*) message;
1990 pkt_len -= sizeof (struct GNUNET_EXIT_TcpServiceStartMessage);
1991 if (NULL != state->specifics.tcp_udp.heap_node)
1992 {
1993 GNUNET_break_op (0);
1994 return GNUNET_SYSERR;
1995 }
1996 if (start->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1997 {
1998 GNUNET_break_op (0);
1999 return GNUNET_SYSERR;
2000 }
2001 GNUNET_break_op (ntohl (start->reserved) == 0); 1623 GNUNET_break_op (ntohl (start->reserved) == 0);
2002 /* setup fresh connection */ 1624 /* setup fresh connection */
2003 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1625 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -2011,34 +1633,23 @@ receive_tcp_service (void *cls,
2011 &start->tcp_header, 1633 &start->tcp_header,
2012 &start[1], 1634 &start[1],
2013 pkt_len); 1635 pkt_len);
2014 GNUNET_CADET_receive_done (channel); 1636 GNUNET_CADET_receive_done (state->channel);
2015 return GNUNET_YES;
2016} 1637}
2017 1638
2018 1639
2019/** 1640/**
2020 * Process a request to forward TCP data to the Internet via this peer. 1641 * Check a request to forward TCP data to the Internet via this peer.
2021 * 1642 *
2022 * @param cls closure, NULL 1643 * @param cls our `struct ChannelState *`
2023 * @param channel connection to the other end 1644 * @param start the actual message
2024 * @param channel_ctx pointer to our `struct ChannelState *`
2025 * @param message the actual message
2026 * @return #GNUNET_OK to keep the connection open, 1645 * @return #GNUNET_OK to keep the connection open,
2027 * #GNUNET_SYSERR to close it (signal serious error) 1646 * #GNUNET_SYSERR to close it (signal serious error)
2028 */ 1647 */
2029static int 1648static int
2030receive_tcp_remote (void *cls GNUNET_UNUSED, 1649check_tcp_remote (void *cls,
2031 struct GNUNET_CADET_Channel *channel, 1650 const struct GNUNET_EXIT_TcpInternetStartMessage *start)
2032 void **channel_ctx GNUNET_UNUSED,
2033 const struct GNUNET_MessageHeader *message)
2034{ 1651{
2035 struct ChannelState *state = *channel_ctx; 1652 struct ChannelState *state = cls;
2036 const struct GNUNET_EXIT_TcpInternetStartMessage *start;
2037 uint16_t pkt_len = ntohs (message->size);
2038 const struct in_addr *v4;
2039 const struct in6_addr *v6;
2040 const void *payload;
2041 int af;
2042 1653
2043 if (NULL == state) 1654 if (NULL == state)
2044 { 1655 {
@@ -2050,24 +1661,6 @@ receive_tcp_remote (void *cls GNUNET_UNUSED,
2050 GNUNET_break_op (0); 1661 GNUNET_break_op (0);
2051 return GNUNET_SYSERR; 1662 return GNUNET_SYSERR;
2052 } 1663 }
2053 if (GNUNET_SYSERR == state->is_dns)
2054 {
2055 /* channel is UDP/TCP from now on */
2056 state->is_dns = GNUNET_NO;
2057 }
2058 GNUNET_STATISTICS_update (stats,
2059 gettext_noop ("# Bytes received from CADET"),
2060 pkt_len, GNUNET_NO);
2061 GNUNET_STATISTICS_update (stats,
2062 gettext_noop ("# TCP IP-exit creation requests received via cadet"),
2063 1, GNUNET_NO);
2064 if (pkt_len < sizeof (struct GNUNET_EXIT_TcpInternetStartMessage))
2065 {
2066 GNUNET_break_op (0);
2067 return GNUNET_SYSERR;
2068 }
2069 start = (const struct GNUNET_EXIT_TcpInternetStartMessage*) message;
2070 pkt_len -= sizeof (struct GNUNET_EXIT_TcpInternetStartMessage);
2071 if ( (NULL != state->specifics.tcp_udp.serv) || 1664 if ( (NULL != state->specifics.tcp_udp.serv) ||
2072 (NULL != state->specifics.tcp_udp.heap_node) ) 1665 (NULL != state->specifics.tcp_udp.heap_node) )
2073 { 1666 {
@@ -2079,6 +1672,38 @@ receive_tcp_remote (void *cls GNUNET_UNUSED,
2079 GNUNET_break_op (0); 1672 GNUNET_break_op (0);
2080 return GNUNET_SYSERR; 1673 return GNUNET_SYSERR;
2081 } 1674 }
1675 return GNUNET_OK;
1676}
1677
1678
1679/**
1680 * Process a request to forward TCP data to the Internet via this peer.
1681 *
1682 * @param cls our `struct ChannelState *`
1683 * @param start the actual message
1684 */
1685static void
1686handle_tcp_remote (void *cls,
1687 const struct GNUNET_EXIT_TcpInternetStartMessage *start)
1688{
1689 struct ChannelState *state = cls;
1690 uint16_t pkt_len = ntohs (start->header.size) - sizeof (struct GNUNET_EXIT_TcpInternetStartMessage);
1691 const struct in_addr *v4;
1692 const struct in6_addr *v6;
1693 const void *payload;
1694 int af;
1695
1696 if (GNUNET_SYSERR == state->is_dns)
1697 {
1698 /* channel is UDP/TCP from now on */
1699 state->is_dns = GNUNET_NO;
1700 }
1701 GNUNET_STATISTICS_update (stats,
1702 gettext_noop ("# Bytes received from CADET"),
1703 pkt_len, GNUNET_NO);
1704 GNUNET_STATISTICS_update (stats,
1705 gettext_noop ("# TCP IP-exit creation requests received via cadet"),
1706 1, GNUNET_NO);
2082 af = (int) ntohl (start->af); 1707 af = (int) ntohl (start->af);
2083 state->specifics.tcp_udp.ri.remote_address.af = af; 1708 state->specifics.tcp_udp.ri.remote_address.af = af;
2084 switch (af) 1709 switch (af)
@@ -2087,12 +1712,12 @@ receive_tcp_remote (void *cls GNUNET_UNUSED,
2087 if (pkt_len < sizeof (struct in_addr)) 1712 if (pkt_len < sizeof (struct in_addr))
2088 { 1713 {
2089 GNUNET_break_op (0); 1714 GNUNET_break_op (0);
2090 return GNUNET_SYSERR; 1715 return;
2091 } 1716 }
2092 if (! ipv4_exit) 1717 if (! ipv4_exit)
2093 { 1718 {
2094 GNUNET_break_op (0); 1719 GNUNET_break_op (0);
2095 return GNUNET_SYSERR; 1720 return;
2096 } 1721 }
2097 v4 = (const struct in_addr*) &start[1]; 1722 v4 = (const struct in_addr*) &start[1];
2098 payload = &v4[1]; 1723 payload = &v4[1];
@@ -2103,12 +1728,12 @@ receive_tcp_remote (void *cls GNUNET_UNUSED,
2103 if (pkt_len < sizeof (struct in6_addr)) 1728 if (pkt_len < sizeof (struct in6_addr))
2104 { 1729 {
2105 GNUNET_break_op (0); 1730 GNUNET_break_op (0);
2106 return GNUNET_SYSERR; 1731 return;
2107 } 1732 }
2108 if (! ipv6_exit) 1733 if (! ipv6_exit)
2109 { 1734 {
2110 GNUNET_break_op (0); 1735 GNUNET_break_op (0);
2111 return GNUNET_SYSERR; 1736 return;
2112 } 1737 }
2113 v6 = (const struct in6_addr*) &start[1]; 1738 v6 = (const struct in6_addr*) &start[1];
2114 payload = &v6[1]; 1739 payload = &v6[1];
@@ -2117,7 +1742,7 @@ receive_tcp_remote (void *cls GNUNET_UNUSED,
2117 break; 1742 break;
2118 default: 1743 default:
2119 GNUNET_break_op (0); 1744 GNUNET_break_op (0);
2120 return GNUNET_SYSERR; 1745 return;
2121 } 1746 }
2122 { 1747 {
2123 char buf[INET6_ADDRSTRLEN]; 1748 char buf[INET6_ADDRSTRLEN];
@@ -2135,46 +1760,27 @@ receive_tcp_remote (void *cls GNUNET_UNUSED,
2135 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address, 1760 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2136 &state->specifics.tcp_udp.ri.local_address, 1761 &state->specifics.tcp_udp.ri.local_address,
2137 &start->tcp_header, 1762 &start->tcp_header,
2138 payload, pkt_len); 1763 payload,
2139 GNUNET_CADET_receive_done (channel); 1764 pkt_len);
2140 return GNUNET_YES; 1765 GNUNET_CADET_receive_done (state->channel);
2141} 1766}
2142 1767
2143 1768
2144/** 1769/**
2145 * Process a request to forward TCP data on an established 1770 * Check a request to forward TCP data on an established
2146 * connection via this peer. 1771 * connection via this peer.
2147 * 1772 *
2148 * @param cls closure, NULL 1773 * @param cls our `struct ChannelState *`
2149 * @param channel connection to the other end
2150 * @param channel_ctx pointer to our `struct ChannelState *`
2151 * @param message the actual message 1774 * @param message the actual message
2152 * @return #GNUNET_OK to keep the connection open, 1775 * @return #GNUNET_OK to keep the connection open,
2153 * #GNUNET_SYSERR to close it (signal serious error) 1776 * #GNUNET_SYSERR to close it (signal serious error)
2154 */ 1777 */
2155static int 1778static int
2156receive_tcp_data (void *cls GNUNET_UNUSED, 1779check_tcp_data (void *cls,
2157 struct GNUNET_CADET_Channel *channel, 1780 const struct GNUNET_EXIT_TcpDataMessage *data)
2158 void **channel_ctx GNUNET_UNUSED,
2159 const struct GNUNET_MessageHeader *message)
2160{ 1781{
2161 struct ChannelState *state = *channel_ctx; 1782 struct ChannelState *state = cls;
2162 const struct GNUNET_EXIT_TcpDataMessage *data;
2163 uint16_t pkt_len = ntohs (message->size);
2164 1783
2165 GNUNET_STATISTICS_update (stats,
2166 gettext_noop ("# Bytes received from CADET"),
2167 pkt_len, GNUNET_NO);
2168 GNUNET_STATISTICS_update (stats,
2169 gettext_noop ("# TCP data requests received via cadet"),
2170 1, GNUNET_NO);
2171 if (pkt_len < sizeof (struct GNUNET_EXIT_TcpDataMessage))
2172 {
2173 GNUNET_break_op (0);
2174 return GNUNET_SYSERR;
2175 }
2176 data = (const struct GNUNET_EXIT_TcpDataMessage*) message;
2177 pkt_len -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
2178 if ( (NULL == state) || 1784 if ( (NULL == state) ||
2179 (NULL == state->specifics.tcp_udp.heap_node) ) 1785 (NULL == state->specifics.tcp_udp.heap_node) )
2180 { 1786 {
@@ -2195,6 +1801,30 @@ receive_tcp_data (void *cls GNUNET_UNUSED,
2195 GNUNET_break_op (0); 1801 GNUNET_break_op (0);
2196 return GNUNET_SYSERR; 1802 return GNUNET_SYSERR;
2197 } 1803 }
1804 return GNUNET_OK;
1805}
1806
1807
1808/**
1809 * Process a request to forward TCP data on an established
1810 * connection via this peer.
1811 *
1812 * @param cls our `struct ChannelState *`
1813 * @param message the actual message
1814 */
1815static void
1816handle_tcp_data (void *cls,
1817 const struct GNUNET_EXIT_TcpDataMessage *data)
1818{
1819 struct ChannelState *state = cls;
1820 uint16_t pkt_len = ntohs (data->header.size) - sizeof (struct GNUNET_EXIT_TcpDataMessage);
1821
1822 GNUNET_STATISTICS_update (stats,
1823 gettext_noop ("# Bytes received from CADET"),
1824 pkt_len, GNUNET_NO);
1825 GNUNET_STATISTICS_update (stats,
1826 gettext_noop ("# TCP data requests received via cadet"),
1827 1, GNUNET_NO);
2198 if (GNUNET_SYSERR == state->is_dns) 1828 if (GNUNET_SYSERR == state->is_dns)
2199 { 1829 {
2200 /* channel is UDP/TCP from now on */ 1830 /* channel is UDP/TCP from now on */
@@ -2218,110 +1848,7 @@ receive_tcp_data (void *cls GNUNET_UNUSED,
2218 &state->specifics.tcp_udp.ri.local_address, 1848 &state->specifics.tcp_udp.ri.local_address,
2219 &data->tcp_header, 1849 &data->tcp_header,
2220 &data[1], pkt_len); 1850 &data[1], pkt_len);
2221 GNUNET_CADET_receive_done (channel); 1851 GNUNET_CADET_receive_done (state->channel);
2222 return GNUNET_YES;
2223}
2224
2225
2226/**
2227 * Send an ICMP packet via the TUN interface.
2228 *
2229 * @param destination_address IP to use for the ICMP packet's destination
2230 * @param source_address IP to use for the ICMP packet's source
2231 * @param icmp_header ICMP header to send
2232 * @param payload payload of the ICMP packet (does NOT include ICMP header)
2233 * @param payload_length number of bytes of data in @a payload
2234 */
2235static void
2236send_icmp_packet_via_tun (const struct SocketAddress *destination_address,
2237 const struct SocketAddress *source_address,
2238 const struct GNUNET_TUN_IcmpHeader *icmp_header,
2239 const void *payload, size_t payload_length)
2240{
2241 size_t len;
2242 struct GNUNET_TUN_IcmpHeader *icmp;
2243
2244 GNUNET_STATISTICS_update (stats,
2245 gettext_noop ("# ICMP packets sent via TUN"),
2246 1, GNUNET_NO);
2247 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2248 "Sending packet with %u bytes ICMP payload via TUN\n",
2249 (unsigned int) payload_length);
2250 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
2251 switch (destination_address->af)
2252 {
2253 case AF_INET:
2254 len += sizeof (struct GNUNET_TUN_IPv4Header);
2255 break;
2256 case AF_INET6:
2257 len += sizeof (struct GNUNET_TUN_IPv6Header);
2258 break;
2259 default:
2260 GNUNET_break (0);
2261 return;
2262 }
2263 len += sizeof (struct GNUNET_TUN_IcmpHeader);
2264 len += payload_length;
2265 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2266 {
2267 GNUNET_break (0);
2268 return;
2269 }
2270 {
2271 char buf[len] GNUNET_ALIGN;
2272 struct GNUNET_MessageHeader *hdr;
2273 struct GNUNET_TUN_Layer2PacketHeader *tun;
2274
2275 hdr= (struct GNUNET_MessageHeader *) buf;
2276 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2277 hdr->size = htons (len);
2278 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
2279 tun->flags = htons (0);
2280 switch (source_address->af)
2281 {
2282 case AF_INET:
2283 {
2284 struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
2285
2286 tun->proto = htons (ETH_P_IPV4);
2287 GNUNET_TUN_initialize_ipv4_header (ipv4,
2288 IPPROTO_ICMP,
2289 sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length,
2290 &source_address->address.ipv4,
2291 &destination_address->address.ipv4);
2292 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv4[1];
2293 }
2294 break;
2295 case AF_INET6:
2296 {
2297 struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
2298
2299 tun->proto = htons (ETH_P_IPV6);
2300 GNUNET_TUN_initialize_ipv6_header (ipv6,
2301 IPPROTO_ICMPV6,
2302 sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length,
2303 &source_address->address.ipv6,
2304 &destination_address->address.ipv6);
2305 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv6[1];
2306 }
2307 break;
2308 default:
2309 GNUNET_assert (0);
2310 break;
2311 }
2312 *icmp = *icmp_header;
2313 GNUNET_memcpy (&icmp[1],
2314 payload,
2315 payload_length);
2316 GNUNET_TUN_calculate_icmp_checksum (icmp,
2317 payload,
2318 payload_length);
2319 if (NULL != helper_handle)
2320 (void) GNUNET_HELPER_send (helper_handle,
2321 (const struct GNUNET_MessageHeader*) buf,
2322 GNUNET_YES,
2323 NULL, NULL);
2324 }
2325} 1852}
2326 1853
2327 1854
@@ -2378,35 +1905,46 @@ make_up_icmpv6_payload (struct ChannelState *state,
2378 1905
2379 1906
2380/** 1907/**
2381 * Process a request to forward ICMP data to the Internet via this peer. 1908 * Check a request to forward ICMP data to the Internet via this peer.
2382 * 1909 *
2383 * @param cls closure, NULL 1910 * @param cls our `struct ChannelState *`
2384 * @param channel connection to the other end 1911 * @param msg the actual message
2385 * @param channel_ctx pointer to our 'struct ChannelState *'
2386 * @param message the actual message
2387 * @return #GNUNET_OK to keep the connection open, 1912 * @return #GNUNET_OK to keep the connection open,
2388 * #GNUNET_SYSERR to close it (signal serious error) 1913 * #GNUNET_SYSERR to close it (signal serious error)
2389 */ 1914 */
2390static int 1915static int
2391receive_icmp_remote (void *cls, 1916check_icmp_remote (void *cls,
2392 struct GNUNET_CADET_Channel *channel, 1917 const struct GNUNET_EXIT_IcmpInternetMessage *msg)
2393 void **channel_ctx,
2394 const struct GNUNET_MessageHeader *message)
2395{ 1918{
2396 struct ChannelState *state = *channel_ctx; 1919 struct ChannelState *state = cls;
2397 const struct GNUNET_EXIT_IcmpInternetMessage *msg;
2398 uint16_t pkt_len = ntohs (message->size);
2399 const struct in_addr *v4;
2400 const struct in6_addr *v6;
2401 const void *payload;
2402 char buf[sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2403 int af;
2404 1920
2405 if (GNUNET_YES == state->is_dns) 1921 if (GNUNET_YES == state->is_dns)
2406 { 1922 {
2407 GNUNET_break_op (0); 1923 GNUNET_break_op (0);
2408 return GNUNET_SYSERR; 1924 return GNUNET_SYSERR;
2409 } 1925 }
1926 return GNUNET_OK;
1927}
1928
1929
1930/**
1931 * Process a request to forward ICMP data to the Internet via this peer.
1932 *
1933 * @param cls our `struct ChannelState *`
1934 * @param msg the actual message
1935 */
1936static void
1937handle_icmp_remote (void *cls,
1938 const struct GNUNET_EXIT_IcmpInternetMessage *msg)
1939{
1940 struct ChannelState *state = cls;
1941 uint16_t pkt_len = ntohs (msg->header.size) - sizeof (struct GNUNET_EXIT_IcmpInternetMessage);
1942 const struct in_addr *v4;
1943 const struct in6_addr *v6;
1944 const void *payload;
1945 char buf[sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
1946 int af;
1947
2410 if (GNUNET_SYSERR == state->is_dns) 1948 if (GNUNET_SYSERR == state->is_dns)
2411 { 1949 {
2412 /* channel is UDP/TCP from now on */ 1950 /* channel is UDP/TCP from now on */
@@ -2418,13 +1956,6 @@ receive_icmp_remote (void *cls,
2418 GNUNET_STATISTICS_update (stats, 1956 GNUNET_STATISTICS_update (stats,
2419 gettext_noop ("# ICMP IP-exit requests received via cadet"), 1957 gettext_noop ("# ICMP IP-exit requests received via cadet"),
2420 1, GNUNET_NO); 1958 1, GNUNET_NO);
2421 if (pkt_len < sizeof (struct GNUNET_EXIT_IcmpInternetMessage))
2422 {
2423 GNUNET_break_op (0);
2424 return GNUNET_SYSERR;
2425 }
2426 msg = (const struct GNUNET_EXIT_IcmpInternetMessage*) message;
2427 pkt_len -= sizeof (struct GNUNET_EXIT_IcmpInternetMessage);
2428 1959
2429 af = (int) ntohl (msg->af); 1960 af = (int) ntohl (msg->af);
2430 if ( (NULL != state->specifics.tcp_udp.heap_node) && 1961 if ( (NULL != state->specifics.tcp_udp.heap_node) &&
@@ -2432,7 +1963,7 @@ receive_icmp_remote (void *cls,
2432 { 1963 {
2433 /* other peer switched AF on this channel; not allowed */ 1964 /* other peer switched AF on this channel; not allowed */
2434 GNUNET_break_op (0); 1965 GNUNET_break_op (0);
2435 return GNUNET_SYSERR; 1966 return;
2436 } 1967 }
2437 1968
2438 switch (af) 1969 switch (af)
@@ -2441,12 +1972,12 @@ receive_icmp_remote (void *cls,
2441 if (pkt_len < sizeof (struct in_addr)) 1972 if (pkt_len < sizeof (struct in_addr))
2442 { 1973 {
2443 GNUNET_break_op (0); 1974 GNUNET_break_op (0);
2444 return GNUNET_SYSERR; 1975 return;
2445 } 1976 }
2446 if (! ipv4_exit) 1977 if (! ipv4_exit)
2447 { 1978 {
2448 GNUNET_break_op (0); 1979 GNUNET_break_op (0);
2449 return GNUNET_SYSERR; 1980 return;
2450 } 1981 }
2451 v4 = (const struct in_addr*) &msg[1]; 1982 v4 = (const struct in_addr*) &msg[1];
2452 payload = &v4[1]; 1983 payload = &v4[1];
@@ -2471,7 +2002,7 @@ receive_icmp_remote (void *cls,
2471 if (0 != pkt_len) 2002 if (0 != pkt_len)
2472 { 2003 {
2473 GNUNET_break_op (0); 2004 GNUNET_break_op (0);
2474 return GNUNET_SYSERR; 2005 return;
2475 } 2006 }
2476 /* make up payload */ 2007 /* make up payload */
2477 { 2008 {
@@ -2491,7 +2022,7 @@ receive_icmp_remote (void *cls,
2491 GNUNET_STATISTICS_update (stats, 2022 GNUNET_STATISTICS_update (stats,
2492 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"), 2023 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2493 1, GNUNET_NO); 2024 1, GNUNET_NO);
2494 return GNUNET_SYSERR; 2025 return;
2495 } 2026 }
2496 /* end AF_INET */ 2027 /* end AF_INET */
2497 break; 2028 break;
@@ -2499,12 +2030,12 @@ receive_icmp_remote (void *cls,
2499 if (pkt_len < sizeof (struct in6_addr)) 2030 if (pkt_len < sizeof (struct in6_addr))
2500 { 2031 {
2501 GNUNET_break_op (0); 2032 GNUNET_break_op (0);
2502 return GNUNET_SYSERR; 2033 return;
2503 } 2034 }
2504 if (! ipv6_exit) 2035 if (! ipv6_exit)
2505 { 2036 {
2506 GNUNET_break_op (0); 2037 GNUNET_break_op (0);
2507 return GNUNET_SYSERR; 2038 return;
2508 } 2039 }
2509 v6 = (const struct in6_addr*) &msg[1]; 2040 v6 = (const struct in6_addr*) &msg[1];
2510 payload = &v6[1]; 2041 payload = &v6[1];
@@ -2530,7 +2061,7 @@ receive_icmp_remote (void *cls,
2530 if (0 != pkt_len) 2061 if (0 != pkt_len)
2531 { 2062 {
2532 GNUNET_break_op (0); 2063 GNUNET_break_op (0);
2533 return GNUNET_SYSERR; 2064 return;
2534 } 2065 }
2535 /* make up payload */ 2066 /* make up payload */
2536 { 2067 {
@@ -2550,14 +2081,14 @@ receive_icmp_remote (void *cls,
2550 GNUNET_STATISTICS_update (stats, 2081 GNUNET_STATISTICS_update (stats,
2551 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"), 2082 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2552 1, GNUNET_NO); 2083 1, GNUNET_NO);
2553 return GNUNET_SYSERR; 2084 return;
2554 } 2085 }
2555 /* end AF_INET6 */ 2086 /* end AF_INET6 */
2556 break; 2087 break;
2557 default: 2088 default:
2558 /* bad AF */ 2089 /* bad AF */
2559 GNUNET_break_op (0); 2090 GNUNET_break_op (0);
2560 return GNUNET_SYSERR; 2091 return;
2561 } 2092 }
2562 2093
2563 { 2094 {
@@ -2573,8 +2104,7 @@ receive_icmp_remote (void *cls,
2573 &state->specifics.tcp_udp.ri.local_address, 2104 &state->specifics.tcp_udp.ri.local_address,
2574 &msg->icmp_header, 2105 &msg->icmp_header,
2575 payload, pkt_len); 2106 payload, pkt_len);
2576 GNUNET_CADET_receive_done (channel); 2107 GNUNET_CADET_receive_done (state->channel);
2577 return GNUNET_YES;
2578} 2108}
2579 2109
2580 2110
@@ -2629,28 +2159,19 @@ make_up_icmp_service_payload (struct ChannelState *state,
2629 2159
2630 2160
2631/** 2161/**
2632 * Process a request via cadet to send ICMP data to a service 2162 * Check a request via cadet to send ICMP data to a service
2633 * offered by this system. 2163 * offered by this system.
2634 * 2164 *
2635 * @param cls closure, NULL 2165 * @param cls our `struct ChannelState *`
2636 * @param channel connection to the other end 2166 * @param msg the actual message
2637 * @param channel_ctx pointer to our 'struct ChannelState *'
2638 * @param message the actual message
2639 * @return #GNUNET_OK to keep the connection open, 2167 * @return #GNUNET_OK to keep the connection open,
2640 * #GNUNET_SYSERR to close it (signal serious error) 2168 * #GNUNET_SYSERR to close it (signal serious error)
2641 */ 2169 */
2642static int 2170static int
2643receive_icmp_service (void *cls, 2171check_icmp_service (void *cls,
2644 struct GNUNET_CADET_Channel *channel, 2172 const struct GNUNET_EXIT_IcmpServiceMessage *msg)
2645 void **channel_ctx,
2646 const struct GNUNET_MessageHeader *message)
2647{ 2173{
2648 struct ChannelState *state = *channel_ctx; 2174 struct ChannelState *state = cls;
2649 const struct GNUNET_EXIT_IcmpServiceMessage *msg;
2650 uint16_t pkt_len = ntohs (message->size);
2651 struct GNUNET_TUN_IcmpHeader icmp;
2652 char buf[sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2653 const void *payload;
2654 2175
2655 if (GNUNET_YES == state->is_dns) 2176 if (GNUNET_YES == state->is_dns)
2656 { 2177 {
@@ -2662,6 +2183,27 @@ receive_icmp_service (void *cls,
2662 GNUNET_break_op (0); 2183 GNUNET_break_op (0);
2663 return GNUNET_SYSERR; 2184 return GNUNET_SYSERR;
2664 } 2185 }
2186 return GNUNET_OK;
2187}
2188
2189
2190/**
2191 * Process a request via cadet to send ICMP data to a service
2192 * offered by this system.
2193 *
2194 * @param cls our `struct ChannelState *`
2195 * @param msg the actual message
2196 */
2197static void
2198handle_icmp_service (void *cls,
2199 const struct GNUNET_EXIT_IcmpServiceMessage *msg)
2200{
2201 struct ChannelState *state = cls;
2202 uint16_t pkt_len = ntohs (msg->header.size) - sizeof (struct GNUNET_EXIT_IcmpServiceMessage);
2203 struct GNUNET_TUN_IcmpHeader icmp;
2204 char buf[sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2205 const void *payload;
2206
2665 GNUNET_STATISTICS_update (stats, 2207 GNUNET_STATISTICS_update (stats,
2666 gettext_noop ("# Bytes received from CADET"), 2208 gettext_noop ("# Bytes received from CADET"),
2667 pkt_len, GNUNET_NO); 2209 pkt_len, GNUNET_NO);
@@ -2669,13 +2211,6 @@ receive_icmp_service (void *cls,
2669 gettext_noop ("# ICMP service requests received via cadet"), 2211 gettext_noop ("# ICMP service requests received via cadet"),
2670 1, GNUNET_NO); 2212 1, GNUNET_NO);
2671 /* check that we got at least a valid header */ 2213 /* check that we got at least a valid header */
2672 if (pkt_len < sizeof (struct GNUNET_EXIT_IcmpServiceMessage))
2673 {
2674 GNUNET_break_op (0);
2675 return GNUNET_SYSERR;
2676 }
2677 msg = (const struct GNUNET_EXIT_IcmpServiceMessage*) message;
2678 pkt_len -= sizeof (struct GNUNET_EXIT_IcmpServiceMessage);
2679 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2214 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2680 "Received data from %s for forwarding to ICMP service %s\n", 2215 "Received data from %s for forwarding to ICMP service %s\n",
2681 GNUNET_i2s (&state->peer), 2216 GNUNET_i2s (&state->peer),
@@ -2707,7 +2242,7 @@ receive_icmp_service (void *cls,
2707 if (0 != pkt_len) 2242 if (0 != pkt_len)
2708 { 2243 {
2709 GNUNET_break_op (0); 2244 GNUNET_break_op (0);
2710 return GNUNET_SYSERR; 2245 return;
2711 } 2246 }
2712 payload = buf; 2247 payload = buf;
2713 pkt_len = make_up_icmp_service_payload (state, buf); 2248 pkt_len = make_up_icmp_service_payload (state, buf);
@@ -2718,7 +2253,7 @@ receive_icmp_service (void *cls,
2718 if (0 != pkt_len) 2253 if (0 != pkt_len)
2719 { 2254 {
2720 GNUNET_break_op (0); 2255 GNUNET_break_op (0);
2721 return GNUNET_SYSERR; 2256 return;
2722 } 2257 }
2723 payload = buf; 2258 payload = buf;
2724 pkt_len = make_up_icmp_service_payload (state, buf); 2259 pkt_len = make_up_icmp_service_payload (state, buf);
@@ -2729,12 +2264,12 @@ receive_icmp_service (void *cls,
2729 GNUNET_STATISTICS_update (stats, 2264 GNUNET_STATISTICS_update (stats,
2730 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"), 2265 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
2731 1, GNUNET_NO); 2266 1, GNUNET_NO);
2732 return GNUNET_OK; 2267 return;
2733 } 2268 }
2734 if (0 != pkt_len) 2269 if (0 != pkt_len)
2735 { 2270 {
2736 GNUNET_break_op (0); 2271 GNUNET_break_op (0);
2737 return GNUNET_SYSERR; 2272 return;
2738 } 2273 }
2739 payload = buf; 2274 payload = buf;
2740 pkt_len = make_up_icmp_service_payload (state, buf); 2275 pkt_len = make_up_icmp_service_payload (state, buf);
@@ -2744,7 +2279,7 @@ receive_icmp_service (void *cls,
2744 GNUNET_STATISTICS_update (stats, 2279 GNUNET_STATISTICS_update (stats,
2745 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"), 2280 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2746 1, GNUNET_NO); 2281 1, GNUNET_NO);
2747 return GNUNET_SYSERR; 2282 return;
2748 } 2283 }
2749 /* end of AF_INET */ 2284 /* end of AF_INET */
2750 break; 2285 break;
@@ -2765,7 +2300,7 @@ receive_icmp_service (void *cls,
2765 if (0 != pkt_len) 2300 if (0 != pkt_len)
2766 { 2301 {
2767 GNUNET_break_op (0); 2302 GNUNET_break_op (0);
2768 return GNUNET_SYSERR; 2303 return;
2769 } 2304 }
2770 payload = buf; 2305 payload = buf;
2771 pkt_len = make_up_icmp_service_payload (state, buf); 2306 pkt_len = make_up_icmp_service_payload (state, buf);
@@ -2776,7 +2311,7 @@ receive_icmp_service (void *cls,
2776 if (0 != pkt_len) 2311 if (0 != pkt_len)
2777 { 2312 {
2778 GNUNET_break_op (0); 2313 GNUNET_break_op (0);
2779 return GNUNET_SYSERR; 2314 return;
2780 } 2315 }
2781 payload = buf; 2316 payload = buf;
2782 pkt_len = make_up_icmp_service_payload (state, buf); 2317 pkt_len = make_up_icmp_service_payload (state, buf);
@@ -2788,12 +2323,12 @@ receive_icmp_service (void *cls,
2788 GNUNET_STATISTICS_update (stats, 2323 GNUNET_STATISTICS_update (stats,
2789 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"), 2324 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2790 1, GNUNET_NO); 2325 1, GNUNET_NO);
2791 return GNUNET_OK; 2326 return;
2792 } 2327 }
2793 if (0 != pkt_len) 2328 if (0 != pkt_len)
2794 { 2329 {
2795 GNUNET_break_op (0); 2330 GNUNET_break_op (0);
2796 return GNUNET_SYSERR; 2331 return;
2797 } 2332 }
2798 payload = buf; 2333 payload = buf;
2799 pkt_len = make_up_icmp_service_payload (state, buf); 2334 pkt_len = make_up_icmp_service_payload (state, buf);
@@ -2803,283 +2338,715 @@ receive_icmp_service (void *cls,
2803 GNUNET_STATISTICS_update (stats, 2338 GNUNET_STATISTICS_update (stats,
2804 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"), 2339 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2805 1, GNUNET_NO); 2340 1, GNUNET_NO);
2806 return GNUNET_SYSERR; 2341 return;
2807 } 2342 }
2808 /* end of AF_INET6 */ 2343 /* end of AF_INET6 */
2809 break; 2344 break;
2810 default: 2345 default:
2811 GNUNET_break_op (0); 2346 GNUNET_break_op (0);
2812 return GNUNET_SYSERR; 2347 return;
2813 } 2348 }
2814 2349
2815 send_icmp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address, 2350 send_icmp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2816 &state->specifics.tcp_udp.ri.local_address, 2351 &state->specifics.tcp_udp.ri.local_address,
2817 &icmp, 2352 &icmp,
2818 payload, pkt_len); 2353 payload,
2819 GNUNET_CADET_receive_done (channel); 2354 pkt_len);
2820 return GNUNET_YES; 2355 GNUNET_CADET_receive_done (state->channel);
2821} 2356}
2822 2357
2823 2358
2824/** 2359/**
2825 * Send a UDP packet via the TUN interface. 2360 * Free memory associated with a service record.
2826 * 2361 *
2827 * @param destination_address IP and port to use for the UDP packet's destination 2362 * @param cls unused
2828 * @param source_address IP and port to use for the UDP packet's source 2363 * @param key service descriptor
2829 * @param payload payload of the UDP packet (does NOT include UDP header) 2364 * @param value service record to free
2830 * @param payload_length number of bytes of data in @a payload 2365 * @return #GNUNET_OK
2831 */ 2366 */
2832static void 2367static int
2833send_udp_packet_via_tun (const struct SocketAddress *destination_address, 2368free_service_record (void *cls,
2834 const struct SocketAddress *source_address, 2369 const struct GNUNET_HashCode *key,
2835 const void *payload, size_t payload_length) 2370 void *value)
2836{ 2371{
2837 size_t len; 2372 struct LocalService *service = value;
2373
2374 GNUNET_assert (GNUNET_YES ==
2375 GNUNET_CONTAINER_multihashmap_remove (services,
2376 key,
2377 service));
2378 GNUNET_CADET_close_port (service->port);
2379 GNUNET_free_non_null (service->name);
2380 GNUNET_free (service);
2381 return GNUNET_OK;
2382}
2838 2383
2384
2385/**
2386 * Callback from CADET for new channels.
2387 *
2388 * @param cls closure
2389 * @param channel new handle to the channel
2390 * @param initiator peer that started the channel
2391 * @return initial channel context for the channel
2392 */
2393static void *
2394new_service_channel (void *cls,
2395 struct GNUNET_CADET_Channel *channel,
2396 const struct GNUNET_PeerIdentity *initiator)
2397{
2398 struct LocalService *ls = cls;
2399 struct ChannelState *s = GNUNET_new (struct ChannelState);
2400
2401 s->peer = *initiator;
2839 GNUNET_STATISTICS_update (stats, 2402 GNUNET_STATISTICS_update (stats,
2840 gettext_noop ("# UDP packets sent via TUN"), 2403 gettext_noop ("# Inbound CADET channels created"),
2841 1, GNUNET_NO); 2404 1,
2405 GNUNET_NO);
2842 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2406 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2843 "Sending packet with %u bytes UDP payload via TUN\n", 2407 "Received inbound channel from `%s'\n",
2844 (unsigned int) payload_length); 2408 GNUNET_i2s (initiator));
2845 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader); 2409 s->channel = channel;
2846 switch (source_address->af) 2410 s->specifics.tcp_udp.serv = ls;
2411 s->specifics.tcp_udp.ri.remote_address = ls->address;
2412 return s;
2413}
2414
2415
2416/**
2417 * Function called by cadet whenever an inbound channel is destroyed.
2418 * Should clean up any associated state.
2419 *
2420 * @param cls our `struct ChannelState *`
2421 * @param channel connection to the other end (henceforth invalid)
2422 */
2423static void
2424clean_channel (void *cls,
2425 const struct GNUNET_CADET_Channel *channel)
2426{
2427 struct ChannelState *s = cls;
2428
2429 LOG (GNUNET_ERROR_TYPE_DEBUG,
2430 "Channel destroyed\n");
2431 if (GNUNET_SYSERR == s->is_dns)
2847 { 2432 {
2848 case AF_INET: 2433 GNUNET_free (s);
2849 len += sizeof (struct GNUNET_TUN_IPv4Header);
2850 break;
2851 case AF_INET6:
2852 len += sizeof (struct GNUNET_TUN_IPv6Header);
2853 break;
2854 default:
2855 GNUNET_break (0);
2856 return; 2434 return;
2857 } 2435 }
2858 len += sizeof (struct GNUNET_TUN_UdpHeader); 2436 if (GNUNET_YES == s->is_dns)
2859 len += payload_length;
2860 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2861 { 2437 {
2862 GNUNET_break (0); 2438 if (channels[s->specifics.dns.my_id] == s)
2863 return; 2439 channels[s->specifics.dns.my_id] = NULL;
2864 } 2440 }
2441 else
2865 { 2442 {
2866 char buf[len] GNUNET_ALIGN; 2443 if (NULL != s->specifics.tcp_udp.heap_node)
2867 struct GNUNET_MessageHeader *hdr;
2868 struct GNUNET_TUN_Layer2PacketHeader *tun;
2869
2870 hdr= (struct GNUNET_MessageHeader *) buf;
2871 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2872 hdr->size = htons (len);
2873 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
2874 tun->flags = htons (0);
2875 switch (source_address->af)
2876 { 2444 {
2877 case AF_INET: 2445 GNUNET_assert (GNUNET_YES ==
2878 { 2446 GNUNET_CONTAINER_multihashmap_remove (connections_map,
2879 struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1]; 2447 &s->specifics.tcp_udp.state_key,
2880 2448 s));
2881 tun->proto = htons (ETH_P_IPV4); 2449 GNUNET_CONTAINER_heap_remove_node (s->specifics.tcp_udp.heap_node);
2882 prepare_ipv4_packet (payload, 2450 s->specifics.tcp_udp.heap_node = NULL;
2883 payload_length,
2884 IPPROTO_UDP,
2885 NULL,
2886 source_address,
2887 destination_address,
2888 ipv4);
2889 }
2890 break;
2891 case AF_INET6:
2892 {
2893 struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
2894
2895 tun->proto = htons (ETH_P_IPV6);
2896 prepare_ipv6_packet (payload,
2897 payload_length,
2898 IPPROTO_UDP,
2899 NULL,
2900 source_address,
2901 destination_address,
2902 ipv6);
2903 }
2904 break;
2905 default:
2906 GNUNET_assert (0);
2907 break;
2908 } 2451 }
2909 if (NULL != helper_handle)
2910 (void) GNUNET_HELPER_send (helper_handle,
2911 (const struct GNUNET_MessageHeader*) buf,
2912 GNUNET_YES,
2913 NULL, NULL);
2914 } 2452 }
2453 GNUNET_free (s);
2915} 2454}
2916 2455
2917 2456
2918/** 2457/**
2919 * Process a request to forward UDP data to the Internet via this peer. 2458 * Given a service descriptor and a destination port, find the
2459 * respective service entry.
2920 * 2460 *
2921 * @param cls closure, NULL 2461 * @param proto IPPROTO_TCP or IPPROTO_UDP
2922 * @param channel connection to the other end 2462 * @param name name of the service
2923 * @param channel_ctx pointer to our 'struct ChannelState *' 2463 * @param destination_port destination port
2924 * @param message the actual message 2464 * @param service service information record to store (service->name will be set).
2925 * @return #GNUNET_OK to keep the connection open,
2926 * #GNUNET_SYSERR to close it (signal serious error)
2927 */ 2465 */
2928static int 2466static void
2929receive_udp_remote (void *cls, 2467store_service (int proto,
2930 struct GNUNET_CADET_Channel *channel, 2468 const char *name,
2931 void **channel_ctx, 2469 uint16_t destination_port,
2932 const struct GNUNET_MessageHeader *message) 2470 struct LocalService *service)
2933{ 2471{
2934 struct ChannelState *state = *channel_ctx; 2472 struct GNUNET_MQ_MessageHandler handlers[] = {
2935 const struct GNUNET_EXIT_UdpInternetMessage *msg; 2473 GNUNET_MQ_hd_var_size (icmp_service,
2936 uint16_t pkt_len = ntohs (message->size); 2474 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE,
2937 const struct in_addr *v4; 2475 struct GNUNET_EXIT_IcmpServiceMessage,
2938 const struct in6_addr *v6; 2476 service),
2939 const void *payload; 2477 GNUNET_MQ_hd_var_size (udp_service,
2940 int af; 2478 GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE,
2479 struct GNUNET_EXIT_UdpServiceMessage,
2480 service),
2481 GNUNET_MQ_hd_var_size (tcp_service,
2482 GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START,
2483 struct GNUNET_EXIT_TcpServiceStartMessage,
2484 service),
2485 GNUNET_MQ_hd_var_size (tcp_data,
2486 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT,
2487 struct GNUNET_EXIT_TcpDataMessage,
2488 service),
2489 GNUNET_MQ_handler_end ()
2490 };
2941 2491
2942 if (GNUNET_YES == state->is_dns) 2492 struct GNUNET_HashCode cadet_port;
2493
2494 service->name = GNUNET_strdup (name);
2495 GNUNET_TUN_service_name_to_hash (name,
2496 &service->descriptor);
2497 GNUNET_TUN_compute_service_cadet_port (&service->descriptor,
2498 destination_port,
2499 &cadet_port);
2500 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2501 "Opening CADET port %s for SERVICE exit %s on port %u\n",
2502 GNUNET_h2s (&cadet_port),
2503 name,
2504 (unsigned int) destination_port);
2505 service->port = GNUNET_CADET_open_porT (cadet_handle,
2506 &cadet_port,
2507 &new_service_channel,
2508 service,
2509 NULL,
2510 &clean_channel,
2511 handlers);
2512 service->is_udp = (IPPROTO_UDP == proto);
2513 if (GNUNET_OK !=
2514 GNUNET_CONTAINER_multihashmap_put (services,
2515 &cadet_port,
2516 service,
2517 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
2943 { 2518 {
2944 GNUNET_break_op (0); 2519 GNUNET_CADET_close_port (service->port);
2945 return GNUNET_SYSERR; 2520 GNUNET_free_non_null (service->name);
2521 GNUNET_free (service);
2522 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2523 _("Got duplicate service records for `%s:%u'\n"),
2524 name,
2525 (unsigned int) destination_port);
2946 } 2526 }
2947 if (GNUNET_SYSERR == state->is_dns) 2527}
2528
2529
2530/**
2531 * Send the given packet via the cadet channel.
2532 *
2533 * @param s channel destination
2534 * @param env message to queue
2535 */
2536static void
2537send_packet_to_cadet_channel (struct ChannelState *s,
2538 struct GNUNET_MQ_Envelope *env)
2539{
2540 GNUNET_assert (NULL != s);
2541 GNUNET_STATISTICS_update (stats,
2542 gettext_noop ("# Messages transmitted via cadet channels"),
2543 1,
2544 GNUNET_NO);
2545 GNUNET_MQ_send (GNUNET_CADET_get_mq (s->channel),
2546 env);
2547}
2548
2549
2550/**
2551 * @brief Handles an ICMP packet received from the helper.
2552 *
2553 * @param icmp A pointer to the Packet
2554 * @param pktlen number of bytes in @a icmp
2555 * @param af address family (AFINET or AF_INET6)
2556 * @param destination_ip destination IP-address of the IP packet (should
2557 * be our local address)
2558 * @param source_ip original source IP-address of the IP packet (should
2559 * be the original destination address)
2560 */
2561static void
2562icmp_from_helper (const struct GNUNET_TUN_IcmpHeader *icmp,
2563 size_t pktlen,
2564 int af,
2565 const void *destination_ip,
2566 const void *source_ip)
2567{
2568 struct ChannelState *state;
2569 struct GNUNET_MQ_Envelope *env;
2570 struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
2571 const struct GNUNET_TUN_IPv4Header *ipv4;
2572 const struct GNUNET_TUN_IPv6Header *ipv6;
2573 const struct GNUNET_TUN_UdpHeader *udp;
2574 uint16_t source_port;
2575 uint16_t destination_port;
2576 uint8_t protocol;
2577
2948 { 2578 {
2949 /* channel is UDP/TCP from now on */ 2579 char sbuf[INET6_ADDRSTRLEN];
2950 state->is_dns = GNUNET_NO; 2580 char dbuf[INET6_ADDRSTRLEN];
2581 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2582 "Received ICMP packet going from %s to %s\n",
2583 inet_ntop (af,
2584 source_ip,
2585 sbuf, sizeof (sbuf)),
2586 inet_ntop (af,
2587 destination_ip,
2588 dbuf, sizeof (dbuf)));
2951 } 2589 }
2952 GNUNET_STATISTICS_update (stats, 2590 if (pktlen < sizeof (struct GNUNET_TUN_IcmpHeader))
2953 gettext_noop ("# Bytes received from CADET"),
2954 pkt_len, GNUNET_NO);
2955 GNUNET_STATISTICS_update (stats,
2956 gettext_noop ("# UDP IP-exit requests received via cadet"),
2957 1, GNUNET_NO);
2958 if (pkt_len < sizeof (struct GNUNET_EXIT_UdpInternetMessage))
2959 { 2591 {
2960 GNUNET_break_op (0); 2592 /* blame kernel */
2961 return GNUNET_SYSERR; 2593 GNUNET_break (0);
2594 return;
2962 } 2595 }
2963 msg = (const struct GNUNET_EXIT_UdpInternetMessage*) message; 2596
2964 pkt_len -= sizeof (struct GNUNET_EXIT_UdpInternetMessage); 2597 /* Find out if this is an ICMP packet in response to an existing
2965 af = (int) ntohl (msg->af); 2598 TCP/UDP packet and if so, figure out ports / protocol of the
2966 state->specifics.tcp_udp.ri.remote_address.af = af; 2599 existing session from the IP data in the ICMP payload */
2600 source_port = 0;
2601 destination_port = 0;
2967 switch (af) 2602 switch (af)
2968 { 2603 {
2969 case AF_INET: 2604 case AF_INET:
2970 if (pkt_len < sizeof (struct in_addr)) 2605 protocol = IPPROTO_ICMP;
2971 { 2606 switch (icmp->type)
2972 GNUNET_break_op (0); 2607 {
2973 return GNUNET_SYSERR; 2608 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2974 } 2609 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2975 if (! ipv4_exit) 2610 break;
2976 { 2611 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2977 GNUNET_break_op (0); 2612 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2978 return GNUNET_SYSERR; 2613 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2979 } 2614 if (pktlen <
2980 v4 = (const struct in_addr*) &msg[1]; 2615 sizeof (struct GNUNET_TUN_IcmpHeader) +
2981 payload = &v4[1]; 2616 sizeof (struct GNUNET_TUN_IPv4Header) + 8)
2982 pkt_len -= sizeof (struct in_addr); 2617 {
2983 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4; 2618 /* blame kernel */
2619 GNUNET_break (0);
2620 return;
2621 }
2622 ipv4 = (const struct GNUNET_TUN_IPv4Header *) &icmp[1];
2623 protocol = ipv4->protocol;
2624 /* could be TCP or UDP, but both have the ports in the right
2625 place, so that doesn't matter here */
2626 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2627 /* swap ports, as they are from the original message */
2628 destination_port = ntohs (udp->source_port);
2629 source_port = ntohs (udp->destination_port);
2630 /* throw away ICMP payload, won't be useful for the other side anyway */
2631 pktlen = sizeof (struct GNUNET_TUN_IcmpHeader);
2632 break;
2633 default:
2634 GNUNET_STATISTICS_update (stats,
2635 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2636 1, GNUNET_NO);
2637 return;
2638 }
2984 break; 2639 break;
2985 case AF_INET6: 2640 case AF_INET6:
2986 if (pkt_len < sizeof (struct in6_addr)) 2641 protocol = IPPROTO_ICMPV6;
2987 { 2642 switch (icmp->type)
2988 GNUNET_break_op (0); 2643 {
2989 return GNUNET_SYSERR; 2644 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2990 } 2645 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2991 if (! ipv6_exit) 2646 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2992 { 2647 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2993 GNUNET_break_op (0); 2648 if (pktlen <
2994 return GNUNET_SYSERR; 2649 sizeof (struct GNUNET_TUN_IcmpHeader) +
2995 } 2650 sizeof (struct GNUNET_TUN_IPv6Header) + 8)
2996 v6 = (const struct in6_addr*) &msg[1]; 2651 {
2997 payload = &v6[1]; 2652 /* blame kernel */
2998 pkt_len -= sizeof (struct in6_addr); 2653 GNUNET_break (0);
2999 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6; 2654 return;
2655 }
2656 ipv6 = (const struct GNUNET_TUN_IPv6Header *) &icmp[1];
2657 protocol = ipv6->next_header;
2658 /* could be TCP or UDP, but both have the ports in the right
2659 place, so that doesn't matter here */
2660 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2661 /* swap ports, as they are from the original message */
2662 destination_port = ntohs (udp->source_port);
2663 source_port = ntohs (udp->destination_port);
2664 /* throw away ICMP payload, won't be useful for the other side anyway */
2665 pktlen = sizeof (struct GNUNET_TUN_IcmpHeader);
2666 break;
2667 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2668 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2669 break;
2670 default:
2671 GNUNET_STATISTICS_update (stats,
2672 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2673 1, GNUNET_NO);
2674 return;
2675 }
3000 break; 2676 break;
3001 default: 2677 default:
3002 GNUNET_break_op (0); 2678 GNUNET_assert (0);
3003 return GNUNET_SYSERR;
3004 } 2679 }
2680 switch (protocol)
3005 { 2681 {
3006 char buf[INET6_ADDRSTRLEN]; 2682 case IPPROTO_ICMP:
2683 state = get_redirect_state (af,
2684 IPPROTO_ICMP,
2685 source_ip,
2686 0,
2687 destination_ip,
2688 0,
2689 NULL);
2690 break;
2691 case IPPROTO_ICMPV6:
2692 state = get_redirect_state (af,
2693 IPPROTO_ICMPV6,
2694 source_ip,
2695 0,
2696 destination_ip,
2697 0,
2698 NULL);
2699 break;
2700 case IPPROTO_UDP:
2701 state = get_redirect_state (af,
2702 IPPROTO_UDP,
2703 source_ip,
2704 source_port,
2705 destination_ip,
2706 destination_port,
2707 NULL);
2708 break;
2709 case IPPROTO_TCP:
2710 state = get_redirect_state (af,
2711 IPPROTO_TCP,
2712 source_ip,
2713 source_port,
2714 destination_ip,
2715 destination_port,
2716 NULL);
2717 break;
2718 default:
2719 GNUNET_STATISTICS_update (stats,
2720 gettext_noop ("# ICMP packets dropped (not allowed)"),
2721 1,
2722 GNUNET_NO);
2723 return;
2724 }
2725 if (NULL == state)
2726 {
2727 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2728 _("ICMP Packet dropped, have no matching connection information\n"));
2729 return;
2730 }
2731 env = GNUNET_MQ_msg_extra (i2v,
2732 pktlen - sizeof (struct GNUNET_TUN_IcmpHeader),
2733 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN);
2734 i2v->af = htonl (af);
2735 GNUNET_memcpy (&i2v->icmp_header,
2736 icmp,
2737 pktlen);
2738 send_packet_to_cadet_channel (state,
2739 env);
2740}
2741
2742
2743/**
2744 * @brief Handles an UDP packet received from the helper.
2745 *
2746 * @param udp A pointer to the Packet
2747 * @param pktlen number of bytes in 'udp'
2748 * @param af address family (AFINET or AF_INET6)
2749 * @param destination_ip destination IP-address of the IP packet (should
2750 * be our local address)
2751 * @param source_ip original source IP-address of the IP packet (should
2752 * be the original destination address)
2753 */
2754static void
2755udp_from_helper (const struct GNUNET_TUN_UdpHeader *udp,
2756 size_t pktlen,
2757 int af,
2758 const void *destination_ip,
2759 const void *source_ip)
2760{
2761 struct ChannelState *state;
2762 struct GNUNET_MQ_Envelope *env;
2763 struct GNUNET_EXIT_UdpReplyMessage *urm;
2764
2765 {
2766 char sbuf[INET6_ADDRSTRLEN];
2767 char dbuf[INET6_ADDRSTRLEN];
2768
3007 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2769 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3008 "Received data from %s for forwarding to UDP %s:%u\n", 2770 "Received UDP packet going from %s:%u to %s:%u\n",
3009 GNUNET_i2s (&state->peer),
3010 inet_ntop (af, 2771 inet_ntop (af,
3011 &state->specifics.tcp_udp.ri.remote_address.address, 2772 source_ip,
3012 buf, sizeof (buf)), 2773 sbuf, sizeof (sbuf)),
3013 (unsigned int) ntohs (msg->destination_port)); 2774 (unsigned int) ntohs (udp->source_port),
2775 inet_ntop (af,
2776 destination_ip,
2777 dbuf, sizeof (dbuf)),
2778 (unsigned int) ntohs (udp->destination_port));
3014 } 2779 }
3015 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_UDP; 2780 if (pktlen < sizeof (struct GNUNET_TUN_UdpHeader))
3016 state->specifics.tcp_udp.ri.remote_address.port = msg->destination_port; 2781 {
3017 if (NULL == state->specifics.tcp_udp.heap_node) 2782 /* blame kernel */
3018 setup_state_record (state); 2783 GNUNET_break (0);
3019 if (0 != ntohs (msg->source_port)) 2784 return;
3020 state->specifics.tcp_udp.ri.local_address.port = msg->source_port; 2785 }
3021 send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address, 2786 if (pktlen != ntohs (udp->len))
3022 &state->specifics.tcp_udp.ri.local_address, 2787 {
3023 payload, pkt_len); 2788 /* blame kernel */
3024 GNUNET_CADET_receive_done (channel); 2789 GNUNET_break (0);
3025 return GNUNET_YES; 2790 return;
2791 }
2792 state = get_redirect_state (af,
2793 IPPROTO_UDP,
2794 source_ip,
2795 ntohs (udp->source_port),
2796 destination_ip,
2797 ntohs (udp->destination_port),
2798 NULL);
2799 if (NULL == state)
2800 {
2801 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2802 _("UDP Packet dropped, have no matching connection information\n"));
2803 return;
2804 }
2805 env = GNUNET_MQ_msg_extra (urm,
2806 pktlen - sizeof (struct GNUNET_TUN_UdpHeader),
2807 GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY);
2808 urm->source_port = htons (0);
2809 urm->destination_port = htons (0);
2810 GNUNET_memcpy (&urm[1],
2811 &udp[1],
2812 pktlen - sizeof (struct GNUNET_TUN_UdpHeader));
2813 send_packet_to_cadet_channel (state,
2814 env);
3026} 2815}
3027 2816
3028 2817
3029/** 2818/**
3030 * Process a request via cadet to send a request to a UDP service 2819 * @brief Handles a TCP packet received from the helper.
3031 * offered by this system.
3032 * 2820 *
3033 * @param cls closure, NULL 2821 * @param tcp A pointer to the Packet
3034 * @param channel connection to the other end 2822 * @param pktlen the length of the packet, including its TCP header
3035 * @param channel_ctx pointer to our 'struct ChannelState *' 2823 * @param af address family (AFINET or AF_INET6)
3036 * @param message the actual message 2824 * @param destination_ip destination IP-address of the IP packet (should
3037 * @return #GNUNET_OK to keep the connection open, 2825 * be our local address)
3038 * #GNUNET_SYSERR to close it (signal serious error) 2826 * @param source_ip original source IP-address of the IP packet (should
2827 * be the original destination address)
3039 */ 2828 */
3040static int 2829static void
3041receive_udp_service (void *cls, 2830tcp_from_helper (const struct GNUNET_TUN_TcpHeader *tcp,
3042 struct GNUNET_CADET_Channel *channel, 2831 size_t pktlen,
3043 void **channel_ctx, 2832 int af,
3044 const struct GNUNET_MessageHeader *message) 2833 const void *destination_ip,
2834 const void *source_ip)
3045{ 2835{
3046 struct ChannelState *state = *channel_ctx; 2836 struct ChannelState *state;
3047 const struct GNUNET_EXIT_UdpServiceMessage *msg; 2837 char buf[pktlen] GNUNET_ALIGN;
3048 uint16_t pkt_len = ntohs (message->size); 2838 struct GNUNET_TUN_TcpHeader *mtcp;
2839 struct GNUNET_EXIT_TcpDataMessage *tdm;
2840 struct GNUNET_MQ_Envelope *env;
2841 size_t mlen;
3049 2842
3050 if (NULL == state->specifics.tcp_udp.serv)
3051 { 2843 {
3052 GNUNET_break_op (0); 2844 char sbuf[INET6_ADDRSTRLEN];
3053 return GNUNET_SYSERR; 2845 char dbuf[INET6_ADDRSTRLEN];
2846 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2847 "Received TCP packet with %u bytes going from %s:%u to %s:%u\n",
2848 (unsigned int) (pktlen - sizeof (struct GNUNET_TUN_TcpHeader)),
2849 inet_ntop (af,
2850 source_ip,
2851 sbuf, sizeof (sbuf)),
2852 (unsigned int) ntohs (tcp->source_port),
2853 inet_ntop (af,
2854 destination_ip,
2855 dbuf, sizeof (dbuf)),
2856 (unsigned int) ntohs (tcp->destination_port));
3054 } 2857 }
2858 if (pktlen < sizeof (struct GNUNET_TUN_TcpHeader))
2859 {
2860 /* blame kernel */
2861 GNUNET_break (0);
2862 return;
2863 }
2864 state = get_redirect_state (af,
2865 IPPROTO_TCP,
2866 source_ip,
2867 ntohs (tcp->source_port),
2868 destination_ip,
2869 ntohs (tcp->destination_port),
2870 NULL);
2871 if (NULL == state)
2872 {
2873 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2874 _("TCP Packet dropped, have no matching connection information\n"));
2875
2876 return;
2877 }
2878 /* mug port numbers and crc to avoid information leakage;
2879 sender will need to lookup the correct values anyway */
2880 GNUNET_memcpy (buf, tcp, pktlen);
2881 mtcp = (struct GNUNET_TUN_TcpHeader *) buf;
2882 mtcp->source_port = 0;
2883 mtcp->destination_port = 0;
2884 mtcp->crc = 0;
2885
2886 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) + (pktlen - sizeof (struct GNUNET_TUN_TcpHeader));
2887 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2888 {
2889 GNUNET_break (0);
2890 return;
2891 }
2892 env = GNUNET_MQ_msg_extra (tdm,
2893 pktlen - sizeof (struct GNUNET_TUN_TcpHeader),
2894 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN);
2895 tdm->reserved = htonl (0);
2896 GNUNET_memcpy (&tdm->tcp_header,
2897 buf,
2898 pktlen);
2899 send_packet_to_cadet_channel (state,
2900 env);
2901}
2902
2903
2904/**
2905 * Receive packets from the helper-process
2906 *
2907 * @param cls unused
2908 * @param client unsued
2909 * @param message message received from helper
2910 */
2911static int
2912message_token (void *cls GNUNET_UNUSED,
2913 void *client GNUNET_UNUSED,
2914 const struct GNUNET_MessageHeader *message)
2915{
2916 const struct GNUNET_TUN_Layer2PacketHeader *pkt_tun;
2917 size_t size;
2918
2919 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2920 "Got %u-byte message of type %u from gnunet-helper-exit\n",
2921 ntohs (message->size),
2922 ntohs (message->type));
3055 GNUNET_STATISTICS_update (stats, 2923 GNUNET_STATISTICS_update (stats,
3056 gettext_noop ("# Bytes received from CADET"), 2924 gettext_noop ("# Packets received from TUN"),
3057 pkt_len, GNUNET_NO);
3058 GNUNET_STATISTICS_update (stats,
3059 gettext_noop ("# UDP service requests received via cadet"),
3060 1, GNUNET_NO); 2925 1, GNUNET_NO);
3061 /* check that we got at least a valid header */ 2926 if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
3062 if (pkt_len < sizeof (struct GNUNET_EXIT_UdpServiceMessage))
3063 { 2927 {
3064 GNUNET_break_op (0); 2928 GNUNET_break (0);
3065 return GNUNET_SYSERR; 2929 return GNUNET_OK;
3066 } 2930 }
3067 msg = (const struct GNUNET_EXIT_UdpServiceMessage*) message; 2931 size = ntohs (message->size);
3068 pkt_len -= sizeof (struct GNUNET_EXIT_UdpServiceMessage); 2932 if (size < sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_MessageHeader))
3069 LOG (GNUNET_ERROR_TYPE_DEBUG, 2933 {
3070 "Received data from %s for forwarding to UDP service %s on port %u\n", 2934 GNUNET_break (0);
3071 GNUNET_i2s (&state->peer), 2935 return GNUNET_OK;
3072 GNUNET_h2s (&state->specifics.tcp_udp.serv->descriptor), 2936 }
3073 (unsigned int) ntohs (msg->destination_port)); 2937 GNUNET_STATISTICS_update (stats,
3074 setup_state_record (state); 2938 gettext_noop ("# Bytes received from TUN"),
3075 if (0 != ntohs (msg->source_port)) 2939 size, GNUNET_NO);
3076 state->specifics.tcp_udp.ri.local_address.port = msg->source_port; 2940 pkt_tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
3077 send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address, 2941 size -= sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_MessageHeader);
3078 &state->specifics.tcp_udp.ri.local_address, 2942 switch (ntohs (pkt_tun->proto))
3079 &msg[1], 2943 {
3080 pkt_len); 2944 case ETH_P_IPV4:
3081 GNUNET_CADET_receive_done (channel); 2945 {
3082 return GNUNET_YES; 2946 const struct GNUNET_TUN_IPv4Header *pkt4;
2947
2948 if (size < sizeof (struct GNUNET_TUN_IPv4Header))
2949 {
2950 /* Kernel to blame? */
2951 GNUNET_break (0);
2952 return GNUNET_OK;
2953 }
2954 pkt4 = (const struct GNUNET_TUN_IPv4Header *) &pkt_tun[1];
2955 if (size != ntohs (pkt4->total_length))
2956 {
2957 /* Kernel to blame? */
2958 GNUNET_break (0);
2959 return GNUNET_OK;
2960 }
2961 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
2962 {
2963 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2964 _("IPv4 packet options received. Ignored.\n"));
2965 return GNUNET_OK;
2966 }
2967
2968 size -= sizeof (struct GNUNET_TUN_IPv4Header);
2969 switch (pkt4->protocol)
2970 {
2971 case IPPROTO_UDP:
2972 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt4[1], size,
2973 AF_INET,
2974 &pkt4->destination_address,
2975 &pkt4->source_address);
2976 break;
2977 case IPPROTO_TCP:
2978 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt4[1], size,
2979 AF_INET,
2980 &pkt4->destination_address,
2981 &pkt4->source_address);
2982 break;
2983 case IPPROTO_ICMP:
2984 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt4[1], size,
2985 AF_INET,
2986 &pkt4->destination_address,
2987 &pkt4->source_address);
2988 break;
2989 default:
2990 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2991 _("IPv4 packet with unsupported next header %u received. Ignored.\n"),
2992 (int) pkt4->protocol);
2993 return GNUNET_OK;
2994 }
2995 }
2996 break;
2997 case ETH_P_IPV6:
2998 {
2999 const struct GNUNET_TUN_IPv6Header *pkt6;
3000
3001 if (size < sizeof (struct GNUNET_TUN_IPv6Header))
3002 {
3003 /* Kernel to blame? */
3004 GNUNET_break (0);
3005 return GNUNET_OK;
3006 }
3007 pkt6 = (struct GNUNET_TUN_IPv6Header *) &pkt_tun[1];
3008 if (size != ntohs (pkt6->payload_length) + sizeof (struct GNUNET_TUN_IPv6Header))
3009 {
3010 /* Kernel to blame? */
3011 GNUNET_break (0);
3012 return GNUNET_OK;
3013 }
3014 size -= sizeof (struct GNUNET_TUN_IPv6Header);
3015 switch (pkt6->next_header)
3016 {
3017 case IPPROTO_UDP:
3018 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt6[1], size,
3019 AF_INET6,
3020 &pkt6->destination_address,
3021 &pkt6->source_address);
3022 break;
3023 case IPPROTO_TCP:
3024 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt6[1], size,
3025 AF_INET6,
3026 &pkt6->destination_address,
3027 &pkt6->source_address);
3028 break;
3029 case IPPROTO_ICMPV6:
3030 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt6[1], size,
3031 AF_INET6,
3032 &pkt6->destination_address,
3033 &pkt6->source_address);
3034 break;
3035 default:
3036 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3037 _("IPv6 packet with unsupported next header %d received. Ignored.\n"),
3038 pkt6->next_header);
3039 return GNUNET_OK;
3040 }
3041 }
3042 break;
3043 default:
3044 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3045 _("Packet from unknown protocol %u received. Ignored.\n"),
3046 ntohs (pkt_tun->proto));
3047 break;
3048 }
3049 return GNUNET_OK;
3083} 3050}
3084 3051
3085 3052
@@ -3089,16 +3056,12 @@ receive_udp_service (void *cls,
3089 * @param cls closure 3056 * @param cls closure
3090 * @param channel new handle to the channel 3057 * @param channel new handle to the channel
3091 * @param initiator peer that started the channel 3058 * @param initiator peer that started the channel
3092 * @param port destination port
3093 * @param options channel options flags
3094 * @return initial channel context for the channel 3059 * @return initial channel context for the channel
3095 */ 3060 */
3096static void * 3061static void *
3097new_channel (void *cls, 3062new_channel (void *cls,
3098 struct GNUNET_CADET_Channel *channel, 3063 struct GNUNET_CADET_Channel *channel,
3099 const struct GNUNET_PeerIdentity *initiator, 3064 const struct GNUNET_PeerIdentity *initiator)
3100 const struct GNUNET_HashCode *port,
3101 enum GNUNET_CADET_ChannelOption options)
3102{ 3065{
3103 struct ChannelState *s = GNUNET_new (struct ChannelState); 3066 struct ChannelState *s = GNUNET_new (struct ChannelState);
3104 3067
@@ -3106,7 +3069,8 @@ new_channel (void *cls,
3106 s->peer = *initiator; 3069 s->peer = *initiator;
3107 GNUNET_STATISTICS_update (stats, 3070 GNUNET_STATISTICS_update (stats,
3108 gettext_noop ("# Inbound CADET channels created"), 3071 gettext_noop ("# Inbound CADET channels created"),
3109 1, GNUNET_NO); 3072 1,
3073 GNUNET_NO);
3110 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3074 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3111 "Received inbound channel from `%s'\n", 3075 "Received inbound channel from `%s'\n",
3112 GNUNET_i2s (initiator)); 3076 GNUNET_i2s (initiator));
@@ -3116,64 +3080,6 @@ new_channel (void *cls,
3116 3080
3117 3081
3118/** 3082/**
3119 * Function called by cadet whenever an inbound channel is destroyed.
3120 * Should clean up any associated state.
3121 *
3122 * @param cls closure (set from #GNUNET_CADET_connect)
3123 * @param channel connection to the other end (henceforth invalid)
3124 * @param channel_ctx place where local state associated
3125 * with the channel is stored
3126 */
3127static void
3128clean_channel (void *cls,
3129 const struct GNUNET_CADET_Channel *channel,
3130 void *channel_ctx)
3131{
3132 struct ChannelState *s = channel_ctx;
3133 struct ChannelMessageQueue *tnq;
3134
3135 LOG (GNUNET_ERROR_TYPE_DEBUG,
3136 "Channel destroyed\n");
3137 if (GNUNET_SYSERR == s->is_dns)
3138 {
3139 GNUNET_free (s);
3140 return;
3141 }
3142 if (GNUNET_YES == s->is_dns)
3143 {
3144 if (channels[s->specifics.dns.my_id] == s)
3145 channels[s->specifics.dns.my_id] = NULL;
3146 GNUNET_free_non_null (s->specifics.dns.reply);
3147 }
3148 else
3149 {
3150 while (NULL != (tnq = s->specifics.tcp_udp.head))
3151 {
3152 GNUNET_CONTAINER_DLL_remove (s->specifics.tcp_udp.head,
3153 s->specifics.tcp_udp.tail,
3154 tnq);
3155 GNUNET_free (tnq);
3156 }
3157 if (NULL != s->specifics.tcp_udp.heap_node)
3158 {
3159 GNUNET_assert (GNUNET_YES ==
3160 GNUNET_CONTAINER_multihashmap_remove (connections_map,
3161 &s->specifics.tcp_udp.state_key,
3162 s));
3163 GNUNET_CONTAINER_heap_remove_node (s->specifics.tcp_udp.heap_node);
3164 s->specifics.tcp_udp.heap_node = NULL;
3165 }
3166 }
3167 if (NULL != s->th)
3168 {
3169 GNUNET_CADET_notify_transmit_ready_cancel (s->th);
3170 s->th = NULL;
3171 }
3172 GNUNET_free (s);
3173}
3174
3175
3176/**
3177 * Function that frees everything from a hashmap 3083 * Function that frees everything from a hashmap
3178 * 3084 *
3179 * @param cls unused 3085 * @param cls unused
@@ -3241,6 +3147,21 @@ cleanup (void *cls)
3241 NULL); 3147 NULL);
3242 GNUNET_CONTAINER_multihashmap_destroy (services); 3148 GNUNET_CONTAINER_multihashmap_destroy (services);
3243 } 3149 }
3150 if (NULL != dns_port)
3151 {
3152 GNUNET_CADET_close_port (dns_port);
3153 dns_port = NULL;
3154 }
3155 if (NULL != cadet_port4)
3156 {
3157 GNUNET_CADET_close_port (cadet_port4);
3158 cadet_port4 = NULL;
3159 }
3160 if (NULL != cadet_port6)
3161 {
3162 GNUNET_CADET_close_port (cadet_port6);
3163 cadet_port6 = NULL;
3164 }
3244 if (NULL != cadet_handle) 3165 if (NULL != cadet_handle)
3245 { 3166 {
3246 GNUNET_CADET_disconnect (cadet_handle); 3167 GNUNET_CADET_disconnect (cadet_handle);
@@ -3286,7 +3207,8 @@ cleanup (void *cls)
3286 } 3207 }
3287 if (NULL != stats) 3208 if (NULL != stats)
3288 { 3209 {
3289 GNUNET_STATISTICS_destroy (stats, GNUNET_NO); 3210 GNUNET_STATISTICS_destroy (stats,
3211 GNUNET_NO);
3290 stats = NULL; 3212 stats = NULL;
3291 } 3213 }
3292 for (i=0;i<8;i++) 3214 for (i=0;i<8;i++)
@@ -3614,6 +3536,13 @@ parse_ip_options ()
3614static void 3536static void
3615advertise_dns_exit () 3537advertise_dns_exit ()
3616{ 3538{
3539 struct GNUNET_MQ_MessageHandler handlers[] = {
3540 GNUNET_MQ_hd_var_size (dns_request,
3541 GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET,
3542 struct DnsResponseMessage,
3543 NULL),
3544 GNUNET_MQ_handler_end ()
3545 };
3617 char *dns_exit; 3546 char *dns_exit;
3618 struct GNUNET_HashCode port; 3547 struct GNUNET_HashCode port;
3619 struct in_addr dns_exit4; 3548 struct in_addr dns_exit4;
@@ -3650,10 +3579,13 @@ advertise_dns_exit ()
3650 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3579 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3651 "Opening CADET port %s for DNS exit service\n", 3580 "Opening CADET port %s for DNS exit service\n",
3652 GNUNET_h2s (&port)); 3581 GNUNET_h2s (&port));
3653 GNUNET_CADET_open_port (cadet_handle, 3582 dns_port = GNUNET_CADET_open_porT (cadet_handle,
3654 &port, 3583 &port,
3655 &new_channel, 3584 &new_channel,
3656 NULL); 3585 NULL,
3586 NULL,
3587 &clean_channel,
3588 handlers);
3657 /* advertise exit */ 3589 /* advertise exit */
3658 dht = GNUNET_DHT_connect (cfg, 3590 dht = GNUNET_DHT_connect (cfg,
3659 1); 3591 1);
@@ -3833,16 +3765,24 @@ run (void *cls,
3833 const char *cfgfile, 3765 const char *cfgfile,
3834 const struct GNUNET_CONFIGURATION_Handle *cfg_) 3766 const struct GNUNET_CONFIGURATION_Handle *cfg_)
3835{ 3767{
3836 static struct GNUNET_CADET_MessageHandler handlers[] = { 3768 struct GNUNET_MQ_MessageHandler handlers[] = {
3837 {&receive_icmp_service, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE, 0}, 3769 GNUNET_MQ_hd_var_size (icmp_remote,
3838 {&receive_icmp_remote, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET, 0}, 3770 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET,
3839 {&receive_udp_service, GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE, 0}, 3771 struct GNUNET_EXIT_IcmpInternetMessage,
3840 {&receive_udp_remote, GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET, 0}, 3772 NULL),
3841 {&receive_tcp_service, GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START, 0}, 3773 GNUNET_MQ_hd_var_size (udp_remote,
3842 {&receive_tcp_remote, GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START, 0}, 3774 GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET,
3843 {&receive_tcp_data, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT, 0}, 3775 struct GNUNET_EXIT_UdpInternetMessage,
3844 {&receive_dns_request, GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET, 0}, 3776 NULL),
3845 {NULL, 0, 0} 3777 GNUNET_MQ_hd_var_size (tcp_remote,
3778 GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START,
3779 struct GNUNET_EXIT_TcpInternetStartMessage,
3780 NULL),
3781 GNUNET_MQ_hd_var_size (tcp_data,
3782 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT,
3783 struct GNUNET_EXIT_TcpDataMessage,
3784 NULL),
3785 GNUNET_MQ_handler_end ()
3846 }; 3786 };
3847 struct GNUNET_HashCode port; 3787 struct GNUNET_HashCode port;
3848 char *policy; 3788 char *policy;
@@ -3889,10 +3829,7 @@ run (void *cls,
3889 NULL); 3829 NULL);
3890 stats = GNUNET_STATISTICS_create ("exit", 3830 stats = GNUNET_STATISTICS_create ("exit",
3891 cfg); 3831 cfg);
3892 cadet_handle = GNUNET_CADET_connect (cfg, 3832 cadet_handle = GNUNET_CADET_connecT (cfg);
3893 NULL,
3894 &clean_channel,
3895 handlers);
3896 if (NULL == cadet_handle) 3833 if (NULL == cadet_handle)
3897 { 3834 {
3898 GNUNET_SCHEDULER_shutdown (); 3835 GNUNET_SCHEDULER_shutdown ();
@@ -3925,10 +3862,13 @@ run (void *cls,
3925 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3862 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3926 "Opening CADET port %s for IPv4 gateway service\n", 3863 "Opening CADET port %s for IPv4 gateway service\n",
3927 GNUNET_h2s (&port)); 3864 GNUNET_h2s (&port));
3928 GNUNET_CADET_open_port (cadet_handle, 3865 cadet_port4 = GNUNET_CADET_open_porT (cadet_handle,
3929 &port, 3866 &port,
3930 &new_channel, 3867 &new_channel,
3931 NULL); 3868 NULL,
3869 NULL,
3870 &clean_channel,
3871 handlers);
3932 policy = NULL; 3872 policy = NULL;
3933 if (GNUNET_OK != 3873 if (GNUNET_OK !=
3934 GNUNET_CONFIGURATION_get_value_string (cfg, 3874 GNUNET_CONFIGURATION_get_value_string (cfg,
@@ -3962,10 +3902,13 @@ run (void *cls,
3962 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3902 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3963 "Opening CADET port %s for IPv6 gateway service\n", 3903 "Opening CADET port %s for IPv6 gateway service\n",
3964 GNUNET_h2s (&port)); 3904 GNUNET_h2s (&port));
3965 GNUNET_CADET_open_port (cadet_handle, 3905 cadet_port6 = GNUNET_CADET_open_porT (cadet_handle,
3966 &port, 3906 &port,
3967 &new_channel, 3907 &new_channel,
3968 NULL); 3908 NULL,
3909 NULL,
3910 &clean_channel,
3911 handlers);
3969 policy = NULL; 3912 policy = NULL;
3970 if (GNUNET_OK != 3913 if (GNUNET_OK !=
3971 GNUNET_CONFIGURATION_get_value_string (cfg, 3914 GNUNET_CONFIGURATION_get_value_string (cfg,
diff --git a/src/fs/fs.conf.in b/src/fs/fs.conf.in
index 3534378ae..d46de387f 100644
--- a/src/fs/fs.conf.in
+++ b/src/fs/fs.conf.in
@@ -36,7 +36,7 @@ MAX_PENDING_REQUESTS = 65536
36 36
37# How many requests do we have at most waiting in the queue towards 37# How many requests do we have at most waiting in the queue towards
38# the datastore? (important for memory consumption) 38# the datastore? (important for memory consumption)
39DATASTORE_QUEUE_SIZE = 1024 39DATASTORE_QUEUE_SIZE = 32
40 40
41# Maximum frequency we're allowed to poll the datastore 41# Maximum frequency we're allowed to poll the datastore
42# for content for migration (can be used to reduce 42# for content for migration (can be used to reduce
diff --git a/src/fs/gnunet-service-fs.c b/src/fs/gnunet-service-fs.c
index 8c605c6a2..256d0c2b8 100644
--- a/src/fs/gnunet-service-fs.c
+++ b/src/fs/gnunet-service-fs.c
@@ -1349,7 +1349,7 @@ run (void *cls,
1349 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_INFO, 1349 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_INFO,
1350 "fs", 1350 "fs",
1351 "DATASTORE_QUEUE_SIZE"); 1351 "DATASTORE_QUEUE_SIZE");
1352 dqs = 1024; 1352 dqs = 32;
1353 } 1353 }
1354 GSF_datastore_queue_size = (unsigned int) dqs; 1354 GSF_datastore_queue_size = (unsigned int) dqs;
1355 GSF_enable_randomized_delays = 1355 GSF_enable_randomized_delays =
diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am
index 8c952be04..464bbbca1 100644
--- a/src/gns/Makefile.am
+++ b/src/gns/Makefile.am
@@ -69,8 +69,8 @@ endif
69 69
70libexec_PROGRAMS = \ 70libexec_PROGRAMS = \
71 gnunet-service-gns \ 71 gnunet-service-gns \
72 $(DO_W32_HELPER) \
73 gnunet-dns2gns \ 72 gnunet-dns2gns \
73 $(DO_W32_HELPER) \
74 $(DO_PROXY) 74 $(DO_PROXY)
75 75
76bin_PROGRAMS = \ 76bin_PROGRAMS = \
@@ -136,6 +136,14 @@ gnunet_dns2gns_LDADD = \
136 $(top_builddir)/src/dns/libgnunetdnsstub.la \ 136 $(top_builddir)/src/dns/libgnunetdnsstub.la \
137 $(GN_LIBINTL) 137 $(GN_LIBINTL)
138 138
139if LINUX
140HIJACKBIN = gnunet-dns2gns
141install-exec-hook:
142 $(SUDO_BINARY) setcap 'cap_net_bind_service=+ep' $(DESTDIR)$(libexecdir)/gnunet-dns2gns || true
143else
144install-exec-hook:
145endif
146
139gnunet_gns_proxy_SOURCES = \ 147gnunet_gns_proxy_SOURCES = \
140 gnunet-gns-proxy.c 148 gnunet-gns-proxy.c
141gnunet_gns_proxy_CPPFLAGS = $(AM_CPPFLAGS) $(CPP_GNURL) 149gnunet_gns_proxy_CPPFLAGS = $(AM_CPPFLAGS) $(CPP_GNURL)
diff --git a/src/gns/gnunet-dns2gns.c b/src/gns/gnunet-dns2gns.c
index bb37a42a3..813ecdf8e 100644
--- a/src/gns/gnunet-dns2gns.c
+++ b/src/gns/gnunet-dns2gns.c
@@ -138,7 +138,7 @@ static char *dns_ip;
138/** 138/**
139 * UDP Port we listen on for inbound DNS requests. 139 * UDP Port we listen on for inbound DNS requests.
140 */ 140 */
141static unsigned int listen_port = 2853; 141static unsigned int listen_port = 53;
142 142
143/** 143/**
144 * Which GNS zone do we translate incoming DNS requests to? 144 * Which GNS zone do we translate incoming DNS requests to?
@@ -796,13 +796,17 @@ main (int argc,
796 }; 796 };
797 int ret; 797 int ret;
798 798
799 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, 799 if (GNUNET_OK !=
800 &argc, &argv)) 800 GNUNET_STRINGS_get_utf8_args (argc, argv,
801 &argc, &argv))
801 return 2; 802 return 2;
802 GNUNET_log_setup ("gnunet-dns2gns", "WARNING", NULL); 803 GNUNET_log_setup ("gnunet-dns2gns",
804 "WARNING",
805 NULL);
803 ret = 806 ret =
804 (GNUNET_OK == 807 (GNUNET_OK ==
805 GNUNET_PROGRAM_run (argc, argv, "gnunet-dns2gns", 808 GNUNET_PROGRAM_run (argc, argv,
809 "gnunet-dns2gns",
806 _("GNUnet DNS-to-GNS proxy (a DNS server)"), 810 _("GNUnet DNS-to-GNS proxy (a DNS server)"),
807 options, 811 options,
808 &run, NULL)) ? 0 : 1; 812 &run, NULL)) ? 0 : 1;
diff --git a/src/gns/gnunet-service-gns.c b/src/gns/gnunet-service-gns.c
index 570c07fdf..0ca25ac19 100644
--- a/src/gns/gnunet-service-gns.c
+++ b/src/gns/gnunet-service-gns.c
@@ -328,11 +328,12 @@ handle_lookup (void *cls,
328 char *nameptr = name; 328 char *nameptr = name;
329 const char *utf_in; 329 const char *utf_in;
330 330
331 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
332 "Received LOOKUP message\n");
333 GNUNET_SERVICE_client_continue (gc->client); 331 GNUNET_SERVICE_client_continue (gc->client);
334 utf_in = (const char *) &sh_msg[1]; 332 utf_in = (const char *) &sh_msg[1];
335 GNUNET_STRINGS_utf8_tolower (utf_in, nameptr); 333 GNUNET_STRINGS_utf8_tolower (utf_in, nameptr);
334 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
335 "Received LOOKUP `%s' message\n",
336 name);
336 337
337 clh = GNUNET_new (struct ClientLookupHandle); 338 clh = GNUNET_new (struct ClientLookupHandle);
338 GNUNET_CONTAINER_DLL_insert (gc->clh_head, 339 GNUNET_CONTAINER_DLL_insert (gc->clh_head,
diff --git a/src/identity/gnunet-identity.c b/src/identity/gnunet-identity.c
index f632aa0a8..8c8485249 100644
--- a/src/identity/gnunet-identity.c
+++ b/src/identity/gnunet-identity.c
@@ -29,6 +29,12 @@
29#include "gnunet_util_lib.h" 29#include "gnunet_util_lib.h"
30#include "gnunet_identity_service.h" 30#include "gnunet_identity_service.h"
31 31
32
33/**
34 * Return value from main on timeout.
35 */
36#define TIMEOUT_STATUS_CODE 40
37
32/** 38/**
33 * Handle to IDENTITY service. 39 * Handle to IDENTITY service.
34 */ 40 */
@@ -79,6 +85,11 @@ static struct GNUNET_IDENTITY_Operation *create_op;
79 */ 85 */
80static struct GNUNET_IDENTITY_Operation *delete_op; 86static struct GNUNET_IDENTITY_Operation *delete_op;
81 87
88/**
89 * Value to return from #main().
90 */
91static int global_ret;
92
82 93
83/** 94/**
84 * Task run on shutdown. 95 * Task run on shutdown.
@@ -120,7 +131,11 @@ test_finished ()
120 (NULL == set_ego) && 131 (NULL == set_ego) &&
121 (! list) && 132 (! list) &&
122 (! monitor) ) 133 (! monitor) )
134 {
135 if (TIMEOUT_STATUS_CODE == global_ret)
136 global_ret = 0;
123 GNUNET_SCHEDULER_shutdown (); 137 GNUNET_SCHEDULER_shutdown ();
138 }
124} 139}
125 140
126 141
@@ -159,9 +174,12 @@ create_finished (void *cls,
159 174
160 *op = NULL; 175 *op = NULL;
161 if (NULL != emsg) 176 if (NULL != emsg)
177 {
162 fprintf (stderr, 178 fprintf (stderr,
163 _("Failed to create ego: %s\n"), 179 _("Failed to create ego: %s\n"),
164 emsg); 180 emsg);
181 global_ret = 1;
182 }
165 test_finished (); 183 test_finished ();
166} 184}
167 185
@@ -178,9 +196,12 @@ set_done (void *cls,
178{ 196{
179 set_op = NULL; 197 set_op = NULL;
180 if (NULL != emsg) 198 if (NULL != emsg)
199 {
181 fprintf (stderr, 200 fprintf (stderr,
182 _("Failed to set default ego: %s\n"), 201 _("Failed to set default ego: %s\n"),
183 emsg); 202 emsg);
203 global_ret = 1;
204 }
184 test_finished (); 205 test_finished ();
185} 206}
186 207
@@ -257,17 +278,23 @@ print_ego (void *cls,
257 } 278 }
258 if ( (NULL == ego) && (! monitor) ) 279 if ( (NULL == ego) && (! monitor) )
259 { 280 {
260 GNUNET_SCHEDULER_shutdown (); 281 list = 0;
282 test_finished ();
261 return; 283 return;
262 } 284 }
263 if (! (list | monitor)) 285 if (! (list | monitor))
264 return; 286 return;
265 if (NULL == ego) 287 if (NULL == ego)
266 return; 288 return;
267 GNUNET_IDENTITY_ego_get_public_key (ego, &pk); 289 GNUNET_IDENTITY_ego_get_public_key (ego,
290 &pk);
268 s = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); 291 s = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
269 if ( (monitor) || (NULL != identifier) ) 292 if ( (monitor) ||
270 fprintf (stdout, "%s - %s\n", identifier, s); 293 (NULL != identifier) )
294 fprintf (stdout,
295 "%s - %s\n",
296 identifier,
297 s);
271 GNUNET_free (s); 298 GNUNET_free (s);
272} 299}
273 300
@@ -281,7 +308,9 @@ print_ego (void *cls,
281 * @param cfg configuration 308 * @param cfg configuration
282 */ 309 */
283static void 310static void
284run (void *cls, char *const *args, const char *cfgfile, 311run (void *cls,
312 char *const *args,
313 const char *cfgfile,
285 const struct GNUNET_CONFIGURATION_Handle *cfg) 314 const struct GNUNET_CONFIGURATION_Handle *cfg)
286{ 315{
287 if ( (NULL == set_subsystem) ^ 316 if ( (NULL == set_subsystem) ^
@@ -291,7 +320,9 @@ run (void *cls, char *const *args, const char *cfgfile,
291 "Options -e and -s must always be specified together\n"); 320 "Options -e and -s must always be specified together\n");
292 return; 321 return;
293 } 322 }
294 sh = GNUNET_IDENTITY_connect (cfg, &print_ego, NULL); 323 sh = GNUNET_IDENTITY_connect (cfg,
324 &print_ego,
325 NULL);
295 if (NULL != delete_ego) 326 if (NULL != delete_ego)
296 delete_op = GNUNET_IDENTITY_delete (sh, 327 delete_op = GNUNET_IDENTITY_delete (sh,
297 delete_ego, 328 delete_ego,
@@ -302,7 +333,8 @@ run (void *cls, char *const *args, const char *cfgfile,
302 create_ego, 333 create_ego,
303 &create_finished, 334 &create_finished,
304 &create_op); 335 &create_op);
305 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); 336 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
337 NULL);
306 test_finished (); 338 test_finished ();
307} 339}
308 340
@@ -317,8 +349,6 @@ run (void *cls, char *const *args, const char *cfgfile,
317int 349int
318main (int argc, char *const *argv) 350main (int argc, char *const *argv)
319{ 351{
320 int res;
321
322 static const struct GNUNET_GETOPT_CommandLineOption options[] = { 352 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
323 {'C', "create", "NAME", 353 {'C', "create", "NAME",
324 gettext_noop ("create ego NAME"), 354 gettext_noop ("create ego NAME"),
@@ -340,19 +370,23 @@ main (int argc, char *const *argv)
340 1, &GNUNET_GETOPT_set_string, &set_subsystem}, 370 1, &GNUNET_GETOPT_set_string, &set_subsystem},
341 GNUNET_GETOPT_OPTION_END 371 GNUNET_GETOPT_OPTION_END
342 }; 372 };
373 int res;
343 374
344 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) 375 if (GNUNET_OK !=
345 return 2; 376 GNUNET_STRINGS_get_utf8_args (argc, argv,
346 377 &argc, &argv))
347 res = GNUNET_PROGRAM_run (argc, argv, "gnunet-identity", 378 return 4;
379 global_ret = TIMEOUT_STATUS_CODE; /* timeout */
380 res = GNUNET_PROGRAM_run (argc, argv,
381 "gnunet-identity",
348 gettext_noop ("Maintain egos"), 382 gettext_noop ("Maintain egos"),
349 options, &run, 383 options, &run,
350 NULL); 384 NULL);
351 GNUNET_free ((void *) argv); 385 GNUNET_free ((void *) argv);
352 386
353 if (GNUNET_OK != res) 387 if (GNUNET_OK != res)
354 return 1; 388 return 3;
355 return 0; 389 return global_ret;
356} 390}
357 391
358/* end of gnunet-identity.c */ 392/* end of gnunet-identity.c */
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index eeb9a8a92..8822a6302 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -1640,6 +1640,12 @@ extern "C"
1640 * Demand the whole element from the other 1640 * Demand the whole element from the other
1641 * peer, given only the hash code. 1641 * peer, given only the hash code.
1642 */ 1642 */
1643#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_REQUEST_FULL 565
1644
1645/**
1646 * Demand the whole element from the other
1647 * peer, given only the hash code.
1648 */
1643#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DEMAND 566 1649#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DEMAND 566
1644 1650
1645/** 1651/**
@@ -1795,6 +1801,19 @@ extern "C"
1795 */ 1801 */
1796#define GNUNET_MESSAGE_TYPE_SET_COPY_LAZY_CONNECT 596 1802#define GNUNET_MESSAGE_TYPE_SET_COPY_LAZY_CONNECT 596
1797 1803
1804/**
1805 * Request all missing elements from the other peer,
1806 * based on their sets and the elements we previously sent
1807 * with #GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS.
1808 */
1809#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE 597
1810
1811/**
1812 * Send a set element, not as response to a demand but because
1813 * we're sending the full set.
1814 */
1815#define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_ELEMENT 598
1816
1798 1817
1799/******************************************************************************* 1818/*******************************************************************************
1800 * TESTBED LOGGER message types 1819 * TESTBED LOGGER message types
diff --git a/src/include/gnunet_set_service.h b/src/include/gnunet_set_service.h
index 52613ad59..f9b477f47 100644
--- a/src/include/gnunet_set_service.h
+++ b/src/include/gnunet_set_service.h
@@ -153,6 +153,7 @@ enum GNUNET_SET_Status
153}; 153};
154 154
155 155
156
156/** 157/**
157 * The way results are given to the client. 158 * The way results are given to the client.
158 */ 159 */
@@ -212,6 +213,54 @@ struct GNUNET_SET_Element
212 213
213 214
214/** 215/**
216 * Possible options to pass to a set operation.
217 *
218 * Used as tag for struct #GNUNET_SET_Option.
219 */
220enum GNUNET_SET_OptionType
221{
222 /**
223 * Fail set operations when the other peer shows weird behavior
224 * that might by a Byzantine fault.
225 *
226 * For set union, 'v.num' is a lower bound on elements
227 * that the other peer must have in common with us.
228 */
229 GNUNET_SET_OPTION_BYZANTINE=1,
230 /**
231 * Do not use the optimized set operation, but send full sets.
232 * Might trigger Byzantine fault detection.
233 */
234 GNUNET_SET_OPTION_FORCE_FULL=2,
235 /**
236 * Only use optimized set operations, even though for this
237 * particular set operation they might be much slower.
238 * Might trigger Byzantine fault detection.
239 */
240 GNUNET_SET_OPTION_FORCE_DELTA=4,
241};
242
243
244/**
245 * Option for set operations.
246 */
247struct GNUNET_SET_Option
248{
249 /**
250 * Type of the option.
251 */
252 enum GNUNET_SET_OptionType type;
253
254 /**
255 * Value for the option, only used with some options.
256 */
257 union {
258 uint64_t num;
259 } v;
260};
261
262
263/**
215 * Continuation used for some of the set operations 264 * Continuation used for some of the set operations
216 * 265 *
217 * @param cls closure 266 * @param cls closure
@@ -367,6 +416,7 @@ GNUNET_SET_prepare (const struct GNUNET_PeerIdentity *other_peer,
367 const struct GNUNET_HashCode *app_id, 416 const struct GNUNET_HashCode *app_id,
368 const struct GNUNET_MessageHeader *context_msg, 417 const struct GNUNET_MessageHeader *context_msg,
369 enum GNUNET_SET_ResultMode result_mode, 418 enum GNUNET_SET_ResultMode result_mode,
419 struct GNUNET_SET_Option options[],
370 GNUNET_SET_ResultIterator result_cb, 420 GNUNET_SET_ResultIterator result_cb,
371 void *result_cls); 421 void *result_cls);
372 422
@@ -420,6 +470,7 @@ GNUNET_SET_listen_cancel (struct GNUNET_SET_ListenHandle *lh);
420struct GNUNET_SET_OperationHandle * 470struct GNUNET_SET_OperationHandle *
421GNUNET_SET_accept (struct GNUNET_SET_Request *request, 471GNUNET_SET_accept (struct GNUNET_SET_Request *request,
422 enum GNUNET_SET_ResultMode result_mode, 472 enum GNUNET_SET_ResultMode result_mode,
473 struct GNUNET_SET_Option options[],
423 GNUNET_SET_ResultIterator result_cb, 474 GNUNET_SET_ResultIterator result_cb,
424 void *result_cls); 475 void *result_cls);
425 476
diff --git a/src/namecache/.gitignore b/src/namecache/.gitignore
index 6d2d8488a..2abc07dfb 100644
--- a/src/namecache/.gitignore
+++ b/src/namecache/.gitignore
@@ -4,3 +4,4 @@ test_namecache_api_cache_block
4test_plugin_namecache_postgres 4test_plugin_namecache_postgres
5test_plugin_namecache_sqlite 5test_plugin_namecache_sqlite
6zonefiles 6zonefiles
7test_plugin_namecache_flat
diff --git a/src/namestore/.gitignore b/src/namestore/.gitignore
index 6943b888a..4995a9e36 100644
--- a/src/namestore/.gitignore
+++ b/src/namestore/.gitignore
@@ -18,3 +18,4 @@ test_namestore_api_zone_iteration_specific_zone.nc
18test_namestore_api_zone_iteration_stop.nc 18test_namestore_api_zone_iteration_stop.nc
19test_plugin_namestore_postgres 19test_plugin_namestore_postgres
20test_plugin_namestore_sqlite 20test_plugin_namestore_sqlite
21test_plugin_namestore_flat
diff --git a/src/peerstore/.gitignore b/src/peerstore/.gitignore
index 33304d90b..7fc22bbdb 100644
--- a/src/peerstore/.gitignore
+++ b/src/peerstore/.gitignore
@@ -6,3 +6,4 @@ test_peerstore_api_store
6test_peerstore_api_sync 6test_peerstore_api_sync
7test_peerstore_api_watch 7test_peerstore_api_watch
8test_plugin_peerstore_sqlite 8test_plugin_peerstore_sqlite
9test_plugin_peerstore_flat
diff --git a/src/pt/.gitignore b/src/pt/.gitignore
index 22f803ed6..ea678ffe5 100644
--- a/src/pt/.gitignore
+++ b/src/pt/.gitignore
@@ -1 +1,6 @@
1gnunet-daemon-pt 1gnunet-daemon-pt
2test_gns_vpn
3test_gnunet_vpn-4_over
4test_gnunet_vpn-4_to_6
5test_gnunet_vpn-6_over
6test_gnunet_vpn-6_to_4
diff --git a/src/pt/gnunet-daemon-pt.c b/src/pt/gnunet-daemon-pt.c
index 97ac8e961..54556cc52 100644
--- a/src/pt/gnunet-daemon-pt.c
+++ b/src/pt/gnunet-daemon-pt.c
@@ -864,14 +864,13 @@ handle_dns_response (void *cls,
864 const struct DnsResponseMessage *msg) 864 const struct DnsResponseMessage *msg)
865{ 865{
866 struct CadetExit *exit = cls; 866 struct CadetExit *exit = cls;
867 struct GNUNET_TUN_DnsHeader dns;
868 size_t mlen; 867 size_t mlen;
869 struct RequestContext *rc; 868 struct RequestContext *rc;
870 869
871 mlen = ntohs (msg->header.size) - sizeof (*msg); 870 mlen = ntohs (msg->header.size) - sizeof (*msg);
872 for (rc = exit->receive_queue_head; NULL != rc; rc = rc->next) 871 for (rc = exit->receive_queue_head; NULL != rc; rc = rc->next)
873 { 872 {
874 if (dns.id == rc->dns_id) 873 if (msg->dns.id == rc->dns_id)
875 { 874 {
876 GNUNET_STATISTICS_update (stats, 875 GNUNET_STATISTICS_update (stats,
877 gettext_noop ("# DNS replies received"), 876 gettext_noop ("# DNS replies received"),
diff --git a/src/pt/test_gns_vpn.c b/src/pt/test_gns_vpn.c
index 4b7e817e8..53f27610b 100644
--- a/src/pt/test_gns_vpn.c
+++ b/src/pt/test_gns_vpn.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2007, 2009, 2011, 2012, 2015 Christian Grothoff 3 Copyright (C) 2007, 2009, 2011, 2012, 2015, 2017 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
@@ -22,6 +22,19 @@
22 * @file test_gns_vpn.c 22 * @file test_gns_vpn.c
23 * @brief testcase for accessing VPN services via GNS 23 * @brief testcase for accessing VPN services via GNS
24 * @author Martin Schanzenbach 24 * @author Martin Schanzenbach
25 * @author Christian Grothoff
26 *
27 * This test requires libcurl/libgnurl *with* support for C-ARES.
28 * This is NOT the default on most platforms, which means the test
29 * will be skipped in many cases. Compile libcurl/libgnurl with
30 * "--enable-ares" to get this test to pass.
31 *
32 * Furthermore, the test relies on gnunet-dns2gns being able to bind
33 * to port 53. This means that 'setcap' has to have worked during
34 * 'make install'. If this failed, but everything else is OK, the
35 * test may FAIL hard even though it is just an installation issue (we
36 * cannot conveniently test for the setcap to have worked). However,
37 * you should get a warning that gnunet-dns2gns failed to 'bind'.
25 */ 38 */
26#include "platform.h" 39#include "platform.h"
27#if HAVE_CURL_CURL_H 40#if HAVE_CURL_CURL_H
@@ -39,7 +52,7 @@
39#define PORT 8080 52#define PORT 8080
40#define TEST_DOMAIN "www.gnu" 53#define TEST_DOMAIN "www.gnu"
41 54
42#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) 55#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
43 56
44/** 57/**
45 * Return value for #main(). 58 * Return value for #main().
@@ -96,7 +109,10 @@ static struct CBC cbc;
96 109
97 110
98static size_t 111static size_t
99copy_buffer (void *ptr, size_t size, size_t nmemb, void *ctx) 112copy_buffer (void *ptr,
113 size_t size,
114 size_t nmemb,
115 void *ctx)
100{ 116{
101 struct CBC *cbc = ctx; 117 struct CBC *cbc = ctx;
102 118
@@ -174,6 +190,11 @@ do_shutdown (void *cls)
174 GNUNET_NAMESTORE_cancel (qe); 190 GNUNET_NAMESTORE_cancel (qe);
175 qe = NULL; 191 qe = NULL;
176 } 192 }
193 if (NULL != namestore)
194 {
195 GNUNET_NAMESTORE_disconnect (namestore);
196 namestore = NULL;
197 }
177 GNUNET_free_non_null (url); 198 GNUNET_free_non_null (url);
178 url = NULL; 199 url = NULL;
179} 200}
@@ -280,6 +301,9 @@ curl_main ()
280static void 301static void
281start_curl (void *cls) 302start_curl (void *cls)
282{ 303{
304 CURLcode ec;
305
306 curl_task_id = NULL;
283 GNUNET_asprintf (&url, 307 GNUNET_asprintf (&url,
284 "http://%s/hello_world", 308 "http://%s/hello_world",
285 TEST_DOMAIN); 309 TEST_DOMAIN);
@@ -291,7 +315,18 @@ start_curl (void *cls)
291 curl_easy_setopt (curl, CURLOPT_TIMEOUT, 150L); 315 curl_easy_setopt (curl, CURLOPT_TIMEOUT, 150L);
292 curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, 150L); 316 curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, 150L);
293 curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1); 317 curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1);
294 318 if (CURLE_OK !=
319 (ec = curl_easy_setopt (curl,
320 CURLOPT_DNS_SERVERS,
321 "127.0.0.1:53")))
322 {
323 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
324 "curl build without support for CURLOPT_DNS_SERVERS (%s), cannot run test\n",
325 curl_easy_strerror (ec));
326 global_ret = 77;
327 GNUNET_SCHEDULER_shutdown ();
328 return;
329 }
295 multi = curl_multi_init (); 330 multi = curl_multi_init ();
296 GNUNET_assert (multi != NULL); 331 GNUNET_assert (multi != NULL);
297 GNUNET_assert (CURLM_OK == curl_multi_add_handle (multi, curl)); 332 GNUNET_assert (CURLM_OK == curl_multi_add_handle (multi, curl));
@@ -302,14 +337,6 @@ start_curl (void *cls)
302} 337}
303 338
304 339
305static void
306disco_ns (void* cls)
307{
308 GNUNET_NAMESTORE_disconnect (namestore);
309 namestore = NULL;
310}
311
312
313/** 340/**
314 * Callback invoked from the namestore service once record is 341 * Callback invoked from the namestore service once record is
315 * created. 342 * created.
@@ -328,9 +355,8 @@ commence_testing (void *cls,
328 const char *emsg) 355 const char *emsg)
329{ 356{
330 qe = NULL; 357 qe = NULL;
331 GNUNET_SCHEDULER_add_now (&disco_ns, NULL); 358 if ( (NULL != emsg) &&
332 359 (GNUNET_YES != success) )
333 if ((emsg != NULL) && (GNUNET_YES != success))
334 { 360 {
335 fprintf (stderr, 361 fprintf (stderr,
336 "NS failed to create record %s\n", 362 "NS failed to create record %s\n",
@@ -338,11 +364,14 @@ commence_testing (void *cls,
338 GNUNET_SCHEDULER_shutdown (); 364 GNUNET_SCHEDULER_shutdown ();
339 return; 365 return;
340 } 366 }
367
341 /* wait a little bit before downloading, as we just created the record */ 368 /* wait a little bit before downloading, as we just created the record */
342 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply 369 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
343 (GNUNET_TIME_UNIT_SECONDS, 1), 370 "Launching cURL request\n");
344 &start_curl, 371 curl_task_id
345 NULL); 372 = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
373 &start_curl,
374 NULL);
346} 375}
347 376
348 377
@@ -402,7 +431,6 @@ mhd_main ()
402 431
403 432
404 433
405
406/** 434/**
407 * Open '/dev/null' and make the result the given 435 * Open '/dev/null' and make the result the given
408 * file descriptor. 436 * file descriptor.
@@ -448,9 +476,8 @@ fork_and_exec (const char *file,
448 pid = fork (); 476 pid = fork ();
449 if (-1 == pid) 477 if (-1 == pid)
450 { 478 {
451 fprintf (stderr, 479 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
452 "fork failed: %s\n", 480 "fork");
453 strerror (errno));
454 return 1; 481 return 1;
455 } 482 }
456 if (0 == pid) 483 if (0 == pid)
@@ -464,10 +491,9 @@ fork_and_exec (const char *file,
464 open_dev_null (1, O_WRONLY); 491 open_dev_null (1, O_WRONLY);
465 (void) execv (file, cmd); 492 (void) execv (file, cmd);
466 /* can only get here on error */ 493 /* can only get here on error */
467 fprintf (stderr, 494 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
468 "exec `%s' failed: %s\n", 495 "exec",
469 file, 496 file);
470 strerror (errno));
471 _exit (1); 497 _exit (1);
472 } 498 }
473 /* keep running waitpid as long as the only error we get is 'EINTR' */ 499 /* keep running waitpid as long as the only error we get is 'EINTR' */
@@ -475,13 +501,20 @@ fork_and_exec (const char *file,
475 (errno == EINTR) ); 501 (errno == EINTR) );
476 if (-1 == ret) 502 if (-1 == ret)
477 { 503 {
478 fprintf (stderr, 504 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
479 "waitpid failed: %s\n", 505 "waitpid");
480 strerror (errno));
481 return 1; 506 return 1;
482 } 507 }
483 if (! (WIFEXITED (status) && (0 == WEXITSTATUS (status)))) 508 if (! (WIFEXITED (status) &&
509 (0 == WEXITSTATUS (status))) )
510 {
511 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
512 "Process `%s` returned status code %d/%d.\n",
513 file,
514 WIFEXITED (status),
515 WEXITSTATUS (status));
484 return 1; 516 return 1;
517 }
485 /* child process completed and returned success, we're happy */ 518 /* child process completed and returned success, we're happy */
486 return 0; 519 return 0;
487} 520}
@@ -572,6 +605,8 @@ identity_cb (void *cls,
572 &rd.data_size)); 605 &rd.data_size));
573 rd.record_type = GNUNET_GNSRECORD_TYPE_VPN; 606 rd.record_type = GNUNET_GNSRECORD_TYPE_VPN;
574 607
608 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
609 "Creating `www` record\n");
575 qe = GNUNET_NAMESTORE_records_store (namestore, 610 qe = GNUNET_NAMESTORE_records_store (namestore,
576 zone_key, 611 zone_key,
577 "www", 612 "www",
@@ -593,15 +628,18 @@ run (void *cls,
593 char *bin; 628 char *bin;
594 char *bin_identity; 629 char *bin_identity;
595 char *bin_gns; 630 char *bin_gns;
631 char *bin_arm;
596 char *config; 632 char *config;
597 633
634 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
635 "Test logic starting...\n");
598 if (GNUNET_OK != 636 if (GNUNET_OK !=
599 GNUNET_CONFIGURATION_get_value_string (cfg, 637 GNUNET_CONFIGURATION_get_value_string (cfg,
600 "arm", 638 "arm",
601 "CONFIG", 639 "CONFIG",
602 &config)) 640 &config))
603 { 641 {
604 fprintf (stderr, 642 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
605 "Failed to locate configuration file. Skipping test.\n"); 643 "Failed to locate configuration file. Skipping test.\n");
606 GNUNET_SCHEDULER_shutdown (); 644 GNUNET_SCHEDULER_shutdown ();
607 return; 645 return;
@@ -626,18 +664,27 @@ run (void *cls,
626 { 664 {
627 "gnunet-identity", 665 "gnunet-identity",
628 "-e", "master-zone", 666 "-e", "master-zone",
629 "-s", "gns-intercept", 667 "-s", "dns2gns",
668 "-c", config,
669 NULL
670 };
671 char *const arm_args[] =
672 {
673 "gnunet-arm",
674 "-i", "dns2gns",
630 "-c", config, 675 "-c", config,
631 NULL 676 NULL
632 }; 677 };
633 char *const gns_args[] = 678 char *const gns_args[] =
634 { 679 {
635 "gnunet-gns", 680 "gnunet-gns",
636 "-u", "www.gns", 681 "-u", "www.gnu",
637 "-c", config, 682 "-c", config,
638 NULL 683 NULL
639 }; 684 };
640 GNUNET_TESTING_peer_get_identity (peer, &id); 685
686 GNUNET_TESTING_peer_get_identity (peer,
687 &id);
641 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, 688 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
642 NULL); 689 NULL);
643 timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, 690 timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
@@ -648,20 +695,24 @@ run (void *cls,
648 "%s/%s", 695 "%s/%s",
649 bin, 696 bin,
650 "gnunet-identity"); 697 "gnunet-identity");
698 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
699 "Creating `master-zone` ego\n");
651 if (0 != fork_and_exec (bin_identity, identity_args)) 700 if (0 != fork_and_exec (bin_identity, identity_args))
652 { 701 {
653 fprintf (stderr, 702 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
654 "Failed to run `gnunet-identity -C. Skipping test.\n"); 703 "Failed to run `gnunet-identity -C`. Skipping test.\n");
655 GNUNET_SCHEDULER_shutdown (); 704 GNUNET_SCHEDULER_shutdown ();
656 GNUNET_free (bin_identity); 705 GNUNET_free (bin_identity);
657 GNUNET_free (config); 706 GNUNET_free (config);
658 GNUNET_free (bin); 707 GNUNET_free (bin);
659 return; 708 return;
660 } 709 }
710 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
711 "Setting `master-zone` ego as default for `gns-master` and `dns2gns`\n");
661 if (0 != fork_and_exec (bin_identity, identity2_args)) 712 if (0 != fork_and_exec (bin_identity, identity2_args))
662 { 713 {
663 fprintf (stderr, 714 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
664 "Failed to run `gnunet-identity -e. Skipping test.\n"); 715 "Failed to run `gnunet-identity -e`. Skipping test.\n");
665 GNUNET_SCHEDULER_shutdown (); 716 GNUNET_SCHEDULER_shutdown ();
666 GNUNET_free (bin_identity); 717 GNUNET_free (bin_identity);
667 GNUNET_free (config); 718 GNUNET_free (config);
@@ -670,8 +721,8 @@ run (void *cls,
670 } 721 }
671 if (0 != fork_and_exec (bin_identity, identity3_args)) 722 if (0 != fork_and_exec (bin_identity, identity3_args))
672 { 723 {
673 fprintf (stderr, 724 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
674 "Failed to run `gnunet-identity -e. Skipping test.\n"); 725 "Failed to run `gnunet-identity -e`. Skipping test.\n");
675 GNUNET_SCHEDULER_shutdown (); 726 GNUNET_SCHEDULER_shutdown ();
676 GNUNET_free (bin_identity); 727 GNUNET_free (bin_identity);
677 GNUNET_free (config); 728 GNUNET_free (config);
@@ -681,14 +732,17 @@ run (void *cls,
681 GNUNET_free (bin_identity); 732 GNUNET_free (bin_identity);
682 733
683 /* do lookup just to launch GNS service */ 734 /* do lookup just to launch GNS service */
735 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
736 "Resolving `www.gnu` zone entry to launch GNS (will yield no answer yet)\n");
684 GNUNET_asprintf (&bin_gns, 737 GNUNET_asprintf (&bin_gns,
685 "%s/%s", 738 "%s/%s",
686 bin, 739 bin,
687 "gnunet-gns"); 740 "gnunet-gns");
688 if (0 != fork_and_exec (bin_gns, gns_args)) 741 if (0 != fork_and_exec (bin_gns,
742 gns_args))
689 { 743 {
690 fprintf (stderr, 744 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
691 "Failed to run `gnunet-gns -u. Skipping test.\n"); 745 "Failed to run `gnunet-gns -u. Skipping test.\n");
692 GNUNET_SCHEDULER_shutdown (); 746 GNUNET_SCHEDULER_shutdown ();
693 GNUNET_free (bin_gns); 747 GNUNET_free (bin_gns);
694 GNUNET_free (config); 748 GNUNET_free (config);
@@ -696,9 +750,27 @@ run (void *cls,
696 return; 750 return;
697 } 751 }
698 GNUNET_free (bin_gns); 752 GNUNET_free (bin_gns);
753
754 GNUNET_asprintf (&bin_arm,
755 "%s/%s",
756 bin,
757 "gnunet-arm");
758 if (0 != fork_and_exec (bin_arm,
759 arm_args))
760 {
761 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
762 "Failed to run `gnunet-arm -i dns2gns. Skipping test.\n");
763 GNUNET_SCHEDULER_shutdown ();
764 GNUNET_free (bin_arm);
765 GNUNET_free (config);
766 GNUNET_free (bin);
767 return;
768 }
769 GNUNET_free (bin_arm);
770
699 GNUNET_free (config); 771 GNUNET_free (config);
700 GNUNET_free (bin); 772 GNUNET_free (bin);
701 773 sleep (1); /* give dns2gns chance to really run */
702 774
703 namestore = GNUNET_NAMESTORE_connect (cfg); 775 namestore = GNUNET_NAMESTORE_connect (cfg);
704 GNUNET_assert (NULL != namestore); 776 GNUNET_assert (NULL != namestore);
@@ -720,39 +792,15 @@ run (void *cls,
720 792
721 793
722int 794int
723main (int argc, char *const *argv) 795main (int argc,
796 char *const *argv)
724{ 797{
725 char *sbin_iptables;
726 char *bin_vpn; 798 char *bin_vpn;
727 char *bin_exit; 799 char *bin_exit;
728 char *bin_dns;
729 char *srv_dns;
730 struct stat s;
731 gid_t my_gid;
732 char *const iptables_args[] =
733 {
734 "iptables", "-t", "mangle", "-L", "-v", NULL
735 };
736
737 if (0 == access ("/sbin/iptables", X_OK))
738 sbin_iptables = "/sbin/iptables";
739 else if (0 == access ("/usr/sbin/iptables", X_OK))
740 sbin_iptables = "/usr/sbin/iptables";
741 else
742 {
743 fprintf (stderr,
744 "Executable iptables not found in approved directories: %s, skipping\n",
745 strerror (errno));
746 return 77;
747 }
748
749 if (0 != fork_and_exec (sbin_iptables, iptables_args))
750 {
751 fprintf (stderr,
752 "Failed to run `iptables -t mangle -L -v'. Skipping test.\n");
753 return 77;
754 }
755 800
801 GNUNET_log_setup ("test-gns-vpn",
802 "WARNING",
803 NULL);
756 if (0 != ACCESS ("/dev/net/tun", R_OK)) 804 if (0 != ACCESS ("/dev/net/tun", R_OK))
757 { 805 {
758 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, 806 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
@@ -765,59 +813,26 @@ main (int argc, char *const *argv)
765 813
766 bin_vpn = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn"); 814 bin_vpn = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
767 bin_exit = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-exit"); 815 bin_exit = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-exit");
768 bin_dns = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-dns");
769 srv_dns = GNUNET_OS_get_libexec_binary_path ("gnunet-service-dns");
770 if ( (0 != geteuid ()) && 816 if ( (0 != geteuid ()) &&
771 ( (GNUNET_YES != 817 ( (GNUNET_YES !=
772 GNUNET_OS_check_helper_binary (bin_vpn, GNUNET_YES, "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) || //ipv4 only please! 818 GNUNET_OS_check_helper_binary (bin_vpn,
819 GNUNET_YES,
820 "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) || //ipv4 only please!
773 (GNUNET_YES != 821 (GNUNET_YES !=
774 GNUNET_OS_check_helper_binary (bin_exit, GNUNET_YES, "-d gnunet-vpn - - - 169.1.3.3.7 255.255.255.0")) || //no nat, ipv4 only 822 GNUNET_OS_check_helper_binary (bin_exit,
775 (GNUNET_YES != 823 GNUNET_YES,
776 GNUNET_OS_check_helper_binary (bin_dns, GNUNET_YES, NULL))) ) // TODO: once we have a windows-testcase, add test parameters here 824 "-d gnunet-vpn - - - 169.1.3.3.7 255.255.255.0")) ) ) //no nat, ipv4 only
777 { 825 {
778 fprintf (stderr, 826 fprintf (stderr,
779 "WARNING: gnunet-helper-{exit,vpn,dns} binaries in $PATH are not SUID, refusing to run test (as it would have to fail).\n"); 827 "WARNING: gnunet-helper-{exit,vpn} binaries in $PATH are not SUID, refusing to run test (as it would have to fail).\n");
780 fprintf (stderr, 828 fprintf (stderr,
781 "Change $PATH ('.' in $PATH before $GNUNET_PREFIX/bin is problematic) or permissions (run 'make install' as root) to fix this!\n"); 829 "Change $PATH ('.' in $PATH before $GNUNET_PREFIX/bin is problematic) or permissions (run 'make install' as root) to fix this!\n");
782 GNUNET_free (bin_vpn); 830 GNUNET_free (bin_vpn);
783 GNUNET_free (bin_exit); 831 GNUNET_free (bin_exit);
784 GNUNET_free (bin_dns);
785 GNUNET_free (srv_dns);
786 return 77; 832 return 77;
787 } 833 }
788 GNUNET_free (bin_vpn); 834 GNUNET_free (bin_vpn);
789 GNUNET_free (bin_exit); 835 GNUNET_free (bin_exit);
790 my_gid = getgid ();
791 if ( (0 != stat (bin_dns, &s)) ||
792 (my_gid == s.st_gid) ||
793 ( (0 == (S_ISUID & s.st_mode)) && (0 != getuid()) ) )
794 {
795 fprintf (stderr,
796 "WARNING: %s has wrong permissions (%d, %d, %d), refusing to run test (as it would have to fail).\n",
797 bin_dns,
798 (0 != stat (bin_dns, &s)),
799 (my_gid == s.st_gid),
800 (0 == (S_ISUID & s.st_mode)) || (0 != getuid()) );
801 GNUNET_free (bin_dns);
802 GNUNET_free (srv_dns);
803 return 77;
804 }
805 if ( (0 != stat (srv_dns, &s)) ||
806 (my_gid == s.st_gid) ||
807 (0 == (S_ISGID & s.st_mode)) )
808 {
809 fprintf (stderr,
810 "WARNING: %s has wrong permissions (%d, %d, %d), refusing to run test (as it would have to fail).\n",
811 srv_dns,
812 (0 != stat (bin_dns, &s)),
813 (my_gid == s.st_gid),
814 (0 == (S_ISGID & s.st_mode)) );
815 GNUNET_free (bin_dns);
816 GNUNET_free (srv_dns);
817 return 77;
818 }
819 GNUNET_free (bin_dns);
820 GNUNET_free (srv_dns);
821 836
822 dest_ip = "169.254.86.1"; 837 dest_ip = "169.254.86.1";
823 dest_af = AF_INET; 838 dest_af = AF_INET;
@@ -842,9 +857,11 @@ main (int argc, char *const *argv)
842 } 857 }
843 858
844 859
845 if (0 != GNUNET_TESTING_peer_run ("test-gnunet-vpn", 860 if (0 !=
846 "test_gns_vpn.conf", 861 GNUNET_TESTING_peer_run ("test_gns_vpn",
847 &run, NULL)) 862 "test_gns_vpn.conf",
863 &run,
864 NULL))
848 return 1; 865 return 1;
849 GNUNET_DISK_directory_remove ("/tmp/gnunet-test-vpn"); 866 GNUNET_DISK_directory_remove ("/tmp/gnunet-test-vpn");
850 return global_ret; 867 return global_ret;
diff --git a/src/pt/test_gns_vpn.conf b/src/pt/test_gns_vpn.conf
index ac9724c04..86642465f 100644
--- a/src/pt/test_gns_vpn.conf
+++ b/src/pt/test_gns_vpn.conf
@@ -35,6 +35,10 @@ FORCESTART = YES
35AUTOSTART = NO 35AUTOSTART = NO
36FORCESTART = NO 36FORCESTART = NO
37 37
38[zonemaster]
39AUTOSTART = YES
40FORCESTART = YES
41
38#[vpn] 42#[vpn]
39#PREFIX = valgrind 43#PREFIX = valgrind
40 44
diff --git a/src/revocation/gnunet-service-revocation.c b/src/revocation/gnunet-service-revocation.c
index 2965808fa..b5669d9ea 100644
--- a/src/revocation/gnunet-service-revocation.c
+++ b/src/revocation/gnunet-service-revocation.c
@@ -509,6 +509,7 @@ transmit_task_cb (void *cls)
509 &revocation_set_union_app_id, 509 &revocation_set_union_app_id,
510 NULL, 510 NULL,
511 GNUNET_SET_RESULT_ADDED, 511 GNUNET_SET_RESULT_ADDED,
512 (struct GNUNET_SET_Option[]) { 0 },
512 &add_revocation, 513 &add_revocation,
513 peer_entry); 514 peer_entry);
514 if (GNUNET_OK != 515 if (GNUNET_OK !=
@@ -755,6 +756,7 @@ handle_revocation_union_request (void *cls,
755 } 756 }
756 peer_entry->so = GNUNET_SET_accept (request, 757 peer_entry->so = GNUNET_SET_accept (request,
757 GNUNET_SET_RESULT_ADDED, 758 GNUNET_SET_RESULT_ADDED,
759 (struct GNUNET_SET_Option[]) { 0 },
758 &add_revocation, 760 &add_revocation,
759 peer_entry); 761 peer_entry);
760 if (GNUNET_OK != 762 if (GNUNET_OK !=
diff --git a/src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c b/src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c
index 9f8d98657..34149435c 100644
--- a/src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c
+++ b/src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c
@@ -788,6 +788,7 @@ cb_intersection_request_alice (void *cls,
788 s->intersection_op 788 s->intersection_op
789 = GNUNET_SET_accept (request, 789 = GNUNET_SET_accept (request,
790 GNUNET_SET_RESULT_REMOVED, 790 GNUNET_SET_RESULT_REMOVED,
791 (struct GNUNET_SET_Option[]) { 0 },
791 &cb_intersection_element_removed, 792 &cb_intersection_element_removed,
792 s); 793 s);
793 if (NULL == s->intersection_op) 794 if (NULL == s->intersection_op)
diff --git a/src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c b/src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c
index 7fd69a4ea..db8241bb7 100644
--- a/src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c
+++ b/src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c
@@ -670,6 +670,7 @@ start_intersection (struct BobServiceSession *s)
670 &set_sid, 670 &set_sid,
671 NULL, 671 NULL,
672 GNUNET_SET_RESULT_REMOVED, 672 GNUNET_SET_RESULT_REMOVED,
673 (struct GNUNET_SET_Option[]) { 0 },
673 &cb_intersection_element_removed, 674 &cb_intersection_element_removed,
674 s); 675 s);
675 if (GNUNET_OK != 676 if (GNUNET_OK !=
diff --git a/src/scalarproduct/gnunet-service-scalarproduct_alice.c b/src/scalarproduct/gnunet-service-scalarproduct_alice.c
index 779d84b60..f99ff6168 100644
--- a/src/scalarproduct/gnunet-service-scalarproduct_alice.c
+++ b/src/scalarproduct/gnunet-service-scalarproduct_alice.c
@@ -1022,6 +1022,7 @@ cb_intersection_request_alice (void *cls,
1022 s->intersection_op 1022 s->intersection_op
1023 = GNUNET_SET_accept (request, 1023 = GNUNET_SET_accept (request,
1024 GNUNET_SET_RESULT_REMOVED, 1024 GNUNET_SET_RESULT_REMOVED,
1025 (struct GNUNET_SET_Option[]) { 0 },
1025 &cb_intersection_element_removed, 1026 &cb_intersection_element_removed,
1026 s); 1027 s);
1027 if (NULL == s->intersection_op) 1028 if (NULL == s->intersection_op)
diff --git a/src/scalarproduct/gnunet-service-scalarproduct_bob.c b/src/scalarproduct/gnunet-service-scalarproduct_bob.c
index a2bceba43..efc3bc8ea 100644
--- a/src/scalarproduct/gnunet-service-scalarproduct_bob.c
+++ b/src/scalarproduct/gnunet-service-scalarproduct_bob.c
@@ -964,6 +964,7 @@ start_intersection (struct BobServiceSession *s)
964 &s->session_id, 964 &s->session_id,
965 NULL, 965 NULL,
966 GNUNET_SET_RESULT_REMOVED, 966 GNUNET_SET_RESULT_REMOVED,
967 (struct GNUNET_SET_Option[]) { 0 },
967 &cb_intersection_element_removed, 968 &cb_intersection_element_removed,
968 s); 969 s);
969 if (GNUNET_OK != 970 if (GNUNET_OK !=
@@ -1172,11 +1173,11 @@ handle_bob_client_message (void *cls,
1172 GNUNET_MQ_hd_fixed_size (alices_computation_request, 1173 GNUNET_MQ_hd_fixed_size (alices_computation_request,
1173 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SESSION_INITIALIZATION, 1174 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SESSION_INITIALIZATION,
1174 struct ServiceRequestMessage, 1175 struct ServiceRequestMessage,
1175 s), 1176 NULL),
1176 GNUNET_MQ_hd_var_size (alices_cryptodata_message, 1177 GNUNET_MQ_hd_var_size (alices_cryptodata_message,
1177 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA, 1178 GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA,
1178 struct AliceCryptodataMessage, 1179 struct AliceCryptodataMessage,
1179 s), 1180 NULL),
1180 GNUNET_MQ_handler_end () 1181 GNUNET_MQ_handler_end ()
1181 }; 1182 };
1182 uint32_t contained_count; 1183 uint32_t contained_count;
diff --git a/src/set/gnunet-service-set.c b/src/set/gnunet-service-set.c
index a545e8a06..c48518f08 100644
--- a/src/set/gnunet-service-set.c
+++ b/src/set/gnunet-service-set.c
@@ -1371,6 +1371,14 @@ handle_client_listen (void *cls,
1371 struct GNUNET_MessageHeader, 1371 struct GNUNET_MessageHeader,
1372 NULL), 1372 NULL),
1373 GNUNET_MQ_hd_var_size (p2p_message, 1373 GNUNET_MQ_hd_var_size (p2p_message,
1374 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE,
1375 struct GNUNET_MessageHeader,
1376 NULL),
1377 GNUNET_MQ_hd_var_size (p2p_message,
1378 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_REQUEST_FULL,
1379 struct GNUNET_MessageHeader,
1380 NULL),
1381 GNUNET_MQ_hd_var_size (p2p_message,
1374 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE, 1382 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE,
1375 struct GNUNET_MessageHeader, 1383 struct GNUNET_MessageHeader,
1376 NULL), 1384 NULL),
@@ -1379,6 +1387,10 @@ handle_client_listen (void *cls,
1379 struct GNUNET_MessageHeader, 1387 struct GNUNET_MessageHeader,
1380 NULL), 1388 NULL),
1381 GNUNET_MQ_hd_var_size (p2p_message, 1389 GNUNET_MQ_hd_var_size (p2p_message,
1390 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_ELEMENT,
1391 struct GNUNET_MessageHeader,
1392 NULL),
1393 GNUNET_MQ_hd_var_size (p2p_message,
1382 GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO, 1394 GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO,
1383 struct GNUNET_MessageHeader, 1395 struct GNUNET_MessageHeader,
1384 NULL), 1396 NULL),
@@ -1393,7 +1405,6 @@ handle_client_listen (void *cls,
1393 GNUNET_MQ_handler_end () 1405 GNUNET_MQ_handler_end ()
1394 }; 1406 };
1395 struct Listener *listener; 1407 struct Listener *listener;
1396 struct Operation *op;
1397 1408
1398 if (NULL != listener_get (client)) 1409 if (NULL != listener_get (client))
1399 { 1410 {
@@ -1422,7 +1433,7 @@ handle_client_listen (void *cls,
1422 &channel_end_cb, 1433 &channel_end_cb,
1423 cadet_handlers); 1434 cadet_handlers);
1424 /* check for existing incoming requests the listener might be interested in */ 1435 /* check for existing incoming requests the listener might be interested in */
1425 for (op = incoming_head; NULL != op; op = op->next) 1436 for (struct Operation *op = incoming_head; NULL != op; op = op->next)
1426 { 1437 {
1427 if (NULL == op->spec) 1438 if (NULL == op->spec)
1428 continue; /* no details available yet */ 1439 continue; /* no details available yet */
@@ -1634,6 +1645,18 @@ handle_client_evaluate (void *cls,
1634 struct GNUNET_MessageHeader, 1645 struct GNUNET_MessageHeader,
1635 op), 1646 op),
1636 GNUNET_MQ_hd_var_size (p2p_message, 1647 GNUNET_MQ_hd_var_size (p2p_message,
1648 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE,
1649 struct GNUNET_MessageHeader,
1650 op),
1651 GNUNET_MQ_hd_var_size (p2p_message,
1652 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_REQUEST_FULL,
1653 struct GNUNET_MessageHeader,
1654 op),
1655 GNUNET_MQ_hd_var_size (p2p_message,
1656 GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_ELEMENT,
1657 struct GNUNET_MessageHeader,
1658 op),
1659 GNUNET_MQ_hd_var_size (p2p_message,
1637 GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO, 1660 GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO,
1638 struct GNUNET_MessageHeader, 1661 struct GNUNET_MessageHeader,
1639 op), 1662 op),
@@ -1668,6 +1691,10 @@ handle_client_evaluate (void *cls,
1668 spec->set = set; 1691 spec->set = set;
1669 spec->result_mode = ntohl (msg->result_mode); 1692 spec->result_mode = ntohl (msg->result_mode);
1670 spec->client_request_id = ntohl (msg->request_id); 1693 spec->client_request_id = ntohl (msg->request_id);
1694 spec->byzantine = msg->byzantine;
1695 spec->byzantine_lower_bound = msg->byzantine_lower_bound;
1696 spec->force_full = msg->force_full;
1697 spec->force_delta = msg->force_delta;
1671 context = GNUNET_MQ_extract_nested_mh (msg); 1698 context = GNUNET_MQ_extract_nested_mh (msg);
1672 op->spec = spec; 1699 op->spec = spec;
1673 1700
@@ -2004,6 +2031,10 @@ handle_client_accept (void *cls,
2004 op); 2031 op);
2005 op->spec->client_request_id = ntohl (msg->request_id); 2032 op->spec->client_request_id = ntohl (msg->request_id);
2006 op->spec->result_mode = ntohl (msg->result_mode); 2033 op->spec->result_mode = ntohl (msg->result_mode);
2034 op->spec->byzantine = msg->byzantine;
2035 op->spec->byzantine_lower_bound = msg->byzantine_lower_bound;
2036 op->spec->force_full = msg->force_full;
2037 op->spec->force_delta = msg->force_delta;
2007 2038
2008 // Advance generation values, so that 2039 // Advance generation values, so that
2009 // mutations won't interfer with the running operation. 2040 // mutations won't interfer with the running operation.
diff --git a/src/set/gnunet-service-set.h b/src/set/gnunet-service-set.h
index 1460707fa..68d8fe81f 100644
--- a/src/set/gnunet-service-set.h
+++ b/src/set/gnunet-service-set.h
@@ -119,6 +119,30 @@ struct OperationSpecification
119 * When are elements sent to the client, and which elements are sent? 119 * When are elements sent to the client, and which elements are sent?
120 */ 120 */
121 enum GNUNET_SET_ResultMode result_mode; 121 enum GNUNET_SET_ResultMode result_mode;
122
123 /**
124 * Always use delta operation instead of sending full sets,
125 * even it it's less efficient.
126 */
127 int force_delta;
128
129 /**
130 * Always send full sets, even if delta operations would
131 * be more efficient.
132 */
133 int force_full;
134
135 /**
136 * #GNUNET_YES to fail operations where Byzantine faults
137 * are suspected
138 */
139 int byzantine;
140
141 /**
142 * Lower bound for the set size, used only when
143 * byzantine mode is enabled.
144 */
145 int byzantine_lower_bound;
122}; 146};
123 147
124 148
diff --git a/src/set/gnunet-service-set_protocol.h b/src/set/gnunet-service-set_protocol.h
index 748da15fc..0138b21c7 100644
--- a/src/set/gnunet-service-set_protocol.h
+++ b/src/set/gnunet-service-set_protocol.h
@@ -208,6 +208,20 @@ struct IntersectionDoneMessage
208 struct GNUNET_HashCode element_xor_hash; 208 struct GNUNET_HashCode element_xor_hash;
209}; 209};
210 210
211
212/**
213 * Strata estimator together with the peer's overall set size.
214 */
215struct StrataEstimatorMessage
216{
217 /**
218 * Type: #GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE(C)
219 */
220 struct GNUNET_MessageHeader header;
221
222 uint64_t set_size;
223};
224
211GNUNET_NETWORK_STRUCT_END 225GNUNET_NETWORK_STRUCT_END
212 226
213#endif 227#endif
diff --git a/src/set/gnunet-service-set_union.c b/src/set/gnunet-service-set_union.c
index acaabd94a..ab39a2e8a 100644
--- a/src/set/gnunet-service-set_union.c
+++ b/src/set/gnunet-service-set_union.c
@@ -85,6 +85,7 @@ enum UnionOperationPhase
85 * upon initialization and later via #PHASE_EXPECT_ELEMENTS_AND_REQUESTS. 85 * upon initialization and later via #PHASE_EXPECT_ELEMENTS_AND_REQUESTS.
86 * 86 *
87 * XXX: could use better wording. 87 * XXX: could use better wording.
88 * XXX: repurposed to also expect a "request full set" message, should be renamed
88 * 89 *
89 * After receiving the complete IBF, we enter #PHASE_EXPECT_ELEMENTS 90 * After receiving the complete IBF, we enter #PHASE_EXPECT_ELEMENTS
90 */ 91 */
@@ -115,14 +116,22 @@ enum UnionOperationPhase
115 * In the penultimate phase, 116 * In the penultimate phase,
116 * we wait until all our demands 117 * we wait until all our demands
117 * are satisfied. Then we send a done 118 * are satisfied. Then we send a done
118 * message, and wait for another done message.*/ 119 * message, and wait for another done message.
120 */
119 PHASE_FINISH_WAITING, 121 PHASE_FINISH_WAITING,
120 122
121 /** 123 /**
122 * In the ultimate phase, we wait until 124 * In the ultimate phase, we wait until
123 * our demands are satisfied and then 125 * our demands are satisfied and then
124 * quit (sending another DONE message). */ 126 * quit (sending another DONE message).
125 PHASE_DONE 127 */
128 PHASE_DONE,
129
130 /**
131 * After sending the full set, wait for responses with the elements
132 * that the local peer is missing.
133 */
134 PHASE_FULL_SENDING,
126}; 135};
127 136
128 137
@@ -148,7 +157,7 @@ struct OperationState
148 struct InvertibleBloomFilter *local_ibf; 157 struct InvertibleBloomFilter *local_ibf;
149 158
150 /** 159 /**
151 * Maps IBF-Keys (specific to the current salt) to elements. 160 * Maps unsalted IBF-Keys to elements.
152 * Used as a multihashmap, the keys being the lower 32bit of the IBF-Key. 161 * Used as a multihashmap, the keys being the lower 32bit of the IBF-Key.
153 * Colliding IBF-Keys are linked. 162 * Colliding IBF-Keys are linked.
154 */ 163 */
@@ -183,6 +192,23 @@ struct OperationState
183 * Salt for the IBF we've received and that we're currently decoding. 192 * Salt for the IBF we've received and that we're currently decoding.
184 */ 193 */
185 uint32_t salt_receive; 194 uint32_t salt_receive;
195
196 /**
197 * Number of elements we received from the other peer
198 * that were not in the local set yet.
199 */
200 uint32_t received_fresh;
201
202 /**
203 * Total number of elements received from the other peer.
204 */
205 uint32_t received_total;
206
207 /**
208 * Initial size of our set, just before
209 * the operation started.
210 */
211 uint64_t initial_size;
186}; 212};
187 213
188 214
@@ -203,6 +229,14 @@ struct KeyEntry
203 * is #GNUNET_YES. 229 * is #GNUNET_YES.
204 */ 230 */
205 struct ElementEntry *element; 231 struct ElementEntry *element;
232
233 /**
234 * Did we receive this element?
235 * Even if element->is_foreign is false, we might
236 * have received the element, so this indicates that
237 * the other peer has it.
238 */
239 int received;
206}; 240};
207 241
208 242
@@ -362,6 +396,16 @@ get_ibf_key (const struct GNUNET_HashCode *src)
362 396
363 397
364/** 398/**
399 * Context for #op_get_element_iterator
400 */
401struct GetElementContext
402{
403 struct GNUNET_HashCode hash;
404 struct KeyEntry *k;
405};
406
407
408/**
365 * Iterator over the mapping from IBF keys to element entries. Checks if we 409 * Iterator over the mapping from IBF keys to element entries. Checks if we
366 * have an element with a given GNUNET_HashCode. 410 * have an element with a given GNUNET_HashCode.
367 * 411 *
@@ -372,17 +416,20 @@ get_ibf_key (const struct GNUNET_HashCode *src)
372 * #GNUNET_NO if we've found the element. 416 * #GNUNET_NO if we've found the element.
373 */ 417 */
374static int 418static int
375op_has_element_iterator (void *cls, 419op_get_element_iterator (void *cls,
376 uint32_t key, 420 uint32_t key,
377 void *value) 421 void *value)
378{ 422{
379 struct GNUNET_HashCode *element_hash = cls; 423 struct GetElementContext *ctx = cls;
380 struct KeyEntry *k = value; 424 struct KeyEntry *k = value;
381 425
382 GNUNET_assert (NULL != k); 426 GNUNET_assert (NULL != k);
383 if (0 == GNUNET_CRYPTO_hash_cmp (&k->element->element_hash, 427 if (0 == GNUNET_CRYPTO_hash_cmp (&k->element->element_hash,
384 element_hash)) 428 &ctx->hash))
429 {
430 ctx->k = k;
385 return GNUNET_NO; 431 return GNUNET_NO;
432 }
386 return GNUNET_YES; 433 return GNUNET_YES;
387} 434}
388 435
@@ -395,23 +442,29 @@ op_has_element_iterator (void *cls,
395 * @param element_hash hash of the element to look for 442 * @param element_hash hash of the element to look for
396 * @return #GNUNET_YES if the element has been found, #GNUNET_NO otherwise 443 * @return #GNUNET_YES if the element has been found, #GNUNET_NO otherwise
397 */ 444 */
398static int 445static struct KeyEntry *
399op_has_element (struct Operation *op, 446op_get_element (struct Operation *op,
400 const struct GNUNET_HashCode *element_hash) 447 const struct GNUNET_HashCode *element_hash)
401{ 448{
402 int ret; 449 int ret;
403 struct IBF_Key ibf_key; 450 struct IBF_Key ibf_key;
451 struct GetElementContext ctx = { 0 };
452
453 ctx.hash = *element_hash;
404 454
405 ibf_key = get_ibf_key (element_hash); 455 ibf_key = get_ibf_key (element_hash);
406 ret = GNUNET_CONTAINER_multihashmap32_get_multiple (op->state->key_to_element, 456 ret = GNUNET_CONTAINER_multihashmap32_get_multiple (op->state->key_to_element,
407 (uint32_t) ibf_key.key_val, 457 (uint32_t) ibf_key.key_val,
408 op_has_element_iterator, 458 op_get_element_iterator,
409 (void *) element_hash); 459 &ctx);
410 460
411 /* was the iteration aborted because we found the element? */ 461 /* was the iteration aborted because we found the element? */
412 if (GNUNET_SYSERR == ret) 462 if (GNUNET_SYSERR == ret)
413 return GNUNET_YES; 463 {
414 return GNUNET_NO; 464 GNUNET_assert (NULL != ctx.k);
465 return ctx.k;
466 }
467 return NULL;
415} 468}
416 469
417 470
@@ -427,10 +480,12 @@ op_has_element (struct Operation *op,
427 * 480 *
428 * @param op the union operation 481 * @param op the union operation
429 * @param ee the element entry 482 * @param ee the element entry
483 * @parem received was this element received from the remote peer?
430 */ 484 */
431static void 485static void
432op_register_element (struct Operation *op, 486op_register_element (struct Operation *op,
433 struct ElementEntry *ee) 487 struct ElementEntry *ee,
488 int received)
434{ 489{
435 struct IBF_Key ibf_key; 490 struct IBF_Key ibf_key;
436 struct KeyEntry *k; 491 struct KeyEntry *k;
@@ -439,6 +494,7 @@ op_register_element (struct Operation *op,
439 k = GNUNET_new (struct KeyEntry); 494 k = GNUNET_new (struct KeyEntry);
440 k->element = ee; 495 k->element = ee;
441 k->ibf_key = ibf_key; 496 k->ibf_key = ibf_key;
497 k->received = received;
442 GNUNET_assert (GNUNET_OK == 498 GNUNET_assert (GNUNET_OK ==
443 GNUNET_CONTAINER_multihashmap32_put (op->state->key_to_element, 499 GNUNET_CONTAINER_multihashmap32_put (op->state->key_to_element,
444 (uint32_t) ibf_key.key_val, 500 (uint32_t) ibf_key.key_val,
@@ -524,12 +580,30 @@ init_key_to_element_iterator (void *cls,
524 580
525 GNUNET_assert (GNUNET_NO == ee->remote); 581 GNUNET_assert (GNUNET_NO == ee->remote);
526 582
527 op_register_element (op, ee); 583 op_register_element (op, ee, GNUNET_NO);
528 return GNUNET_YES; 584 return GNUNET_YES;
529} 585}
530 586
531 587
532/** 588/**
589 * Initialize the IBF key to element mapping local to this set
590 * operation.
591 *
592 * @param op the set union operation
593 */
594static void
595initialize_key_to_element (struct Operation *op)
596{
597 unsigned int len;
598
599 GNUNET_assert (NULL == op->state->key_to_element);
600 len = GNUNET_CONTAINER_multihashmap_size (op->spec->set->content->elements);
601 op->state->key_to_element = GNUNET_CONTAINER_multihashmap32_create (len + 1);
602 GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->content->elements, init_key_to_element_iterator, op);
603}
604
605
606/**
533 * Create an ibf with the operation's elements 607 * Create an ibf with the operation's elements
534 * of the specified size 608 * of the specified size
535 * 609 *
@@ -541,15 +615,8 @@ static int
541prepare_ibf (struct Operation *op, 615prepare_ibf (struct Operation *op,
542 uint32_t size) 616 uint32_t size)
543{ 617{
544 if (NULL == op->state->key_to_element) 618 GNUNET_assert (NULL != op->state->key_to_element);
545 {
546 unsigned int len;
547 619
548 len = GNUNET_CONTAINER_multihashmap_size (op->spec->set->content->elements);
549 op->state->key_to_element = GNUNET_CONTAINER_multihashmap32_create (len + 1);
550 GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->content->elements,
551 init_key_to_element_iterator, op);
552 }
553 if (NULL != op->state->local_ibf) 620 if (NULL != op->state->local_ibf)
554 ibf_destroy (op->state->local_ibf); 621 ibf_destroy (op->state->local_ibf);
555 op->state->local_ibf = ibf_create (size, SE_IBF_HASH_NUM); 622 op->state->local_ibf = ibf_create (size, SE_IBF_HASH_NUM);
@@ -648,7 +715,7 @@ send_strata_estimator (struct Operation *op)
648{ 715{
649 const struct StrataEstimator *se = op->state->se; 716 const struct StrataEstimator *se = op->state->se;
650 struct GNUNET_MQ_Envelope *ev; 717 struct GNUNET_MQ_Envelope *ev;
651 struct GNUNET_MessageHeader *strata_msg; 718 struct StrataEstimatorMessage *strata_msg;
652 char *buf; 719 char *buf;
653 size_t len; 720 size_t len;
654 uint16_t type; 721 uint16_t type;
@@ -660,13 +727,14 @@ send_strata_estimator (struct Operation *op)
660 type = GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SEC; 727 type = GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SEC;
661 else 728 else
662 type = GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE; 729 type = GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE;
663 ev = GNUNET_MQ_msg_header_extra (strata_msg, 730 ev = GNUNET_MQ_msg_extra (strata_msg,
664 len, 731 len,
665 type); 732 type);
666 GNUNET_memcpy (&strata_msg[1], 733 GNUNET_memcpy (&strata_msg[1],
667 buf, 734 buf,
668 len); 735 len);
669 GNUNET_free (buf); 736 GNUNET_free (buf);
737 strata_msg->set_size = GNUNET_htonll (GNUNET_CONTAINER_multihashmap_size (op->spec->set->content->elements));
670 GNUNET_MQ_send (op->mq, 738 GNUNET_MQ_send (op->mq,
671 ev); 739 ev);
672 op->state->phase = PHASE_EXPECT_IBF; 740 op->state->phase = PHASE_EXPECT_IBF;
@@ -698,6 +766,47 @@ get_order_from_difference (unsigned int diff)
698 766
699 767
700/** 768/**
769 * Send a set element.
770 *
771 * @param cls the union operation `struct Operation *`
772 * @param key unused
773 * @param value the `struct ElementEntry *` to insert
774 * into the key-to-element mapping
775 * @return #GNUNET_YES (to continue iterating)
776 */
777static int
778send_element_iterator (void *cls,
779 const struct GNUNET_HashCode *key,
780 void *value)
781{
782 struct Operation *op = cls;
783 struct GNUNET_SET_ElementMessage *emsg;
784 struct GNUNET_SET_Element *el = value;
785 struct GNUNET_MQ_Envelope *ev;
786
787 ev = GNUNET_MQ_msg_extra (emsg, el->size, GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_ELEMENT);
788 emsg->element_type = htonl (el->element_type);
789 GNUNET_memcpy (&emsg[1], el->data, el->size);
790 GNUNET_MQ_send (op->mq, ev);
791 return GNUNET_YES;
792}
793
794
795static void
796send_full_set (struct Operation *op)
797{
798 struct GNUNET_MQ_Envelope *ev;
799
800 op->state->phase = PHASE_FULL_SENDING;
801
802 (void) GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->content->elements,
803 &send_element_iterator, op);
804 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE);
805 GNUNET_MQ_send (op->mq, ev);
806}
807
808
809/**
701 * Handle a strata estimator from a remote peer 810 * Handle a strata estimator from a remote peer
702 * 811 *
703 * @param cls the union operation 812 * @param cls the union operation
@@ -713,7 +822,9 @@ handle_p2p_strata_estimator (void *cls,
713{ 822{
714 struct Operation *op = cls; 823 struct Operation *op = cls;
715 struct StrataEstimator *remote_se; 824 struct StrataEstimator *remote_se;
716 int diff; 825 struct StrataEstimatorMessage *msg = (void *) mh;
826 unsigned int diff;
827 uint64_t other_size;
717 size_t len; 828 size_t len;
718 829
719 GNUNET_STATISTICS_update (_GSS_statistics, 830 GNUNET_STATISTICS_update (_GSS_statistics,
@@ -723,11 +834,11 @@ handle_p2p_strata_estimator (void *cls,
723 834
724 if (op->state->phase != PHASE_EXPECT_SE) 835 if (op->state->phase != PHASE_EXPECT_SE)
725 { 836 {
726 fail_union_operation (op);
727 GNUNET_break (0); 837 GNUNET_break (0);
838 fail_union_operation (op);
728 return GNUNET_SYSERR; 839 return GNUNET_SYSERR;
729 } 840 }
730 len = ntohs (mh->size) - sizeof (struct GNUNET_MessageHeader); 841 len = ntohs (mh->size) - sizeof (struct StrataEstimatorMessage);
731 if ( (GNUNET_NO == is_compressed) && 842 if ( (GNUNET_NO == is_compressed) &&
732 (len != SE_STRATA_COUNT * SE_IBF_SIZE * IBF_BUCKET_SIZE) ) 843 (len != SE_STRATA_COUNT * SE_IBF_SIZE * IBF_BUCKET_SIZE) )
733 { 844 {
@@ -735,6 +846,7 @@ handle_p2p_strata_estimator (void *cls,
735 GNUNET_break (0); 846 GNUNET_break (0);
736 return GNUNET_SYSERR; 847 return GNUNET_SYSERR;
737 } 848 }
849 other_size = GNUNET_ntohll (msg->set_size);
738 remote_se = strata_estimator_create (SE_STRATA_COUNT, 850 remote_se = strata_estimator_create (SE_STRATA_COUNT,
739 SE_IBF_SIZE, 851 SE_IBF_SIZE,
740 SE_IBF_HASH_NUM); 852 SE_IBF_HASH_NUM);
@@ -745,7 +857,7 @@ handle_p2p_strata_estimator (void *cls,
745 return GNUNET_SYSERR; 857 return GNUNET_SYSERR;
746 } 858 }
747 if (GNUNET_OK != 859 if (GNUNET_OK !=
748 strata_estimator_read (&mh[1], 860 strata_estimator_read (&msg[1],
749 len, 861 len,
750 is_compressed, 862 is_compressed,
751 remote_se)) 863 remote_se))
@@ -765,16 +877,46 @@ handle_p2p_strata_estimator (void *cls,
765 "got se diff=%d, using ibf size %d\n", 877 "got se diff=%d, using ibf size %d\n",
766 diff, 878 diff,
767 1<<get_order_from_difference (diff)); 879 1<<get_order_from_difference (diff));
768 if (GNUNET_OK != 880
769 send_ibf (op, 881 if ((GNUNET_YES == op->spec->byzantine) && (other_size < op->spec->byzantine_lower_bound))
770 get_order_from_difference (diff)))
771 { 882 {
772 /* Internal error, best we can do is shut the connection */ 883 GNUNET_break (0);
773 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
774 "Failed to send IBF, closing connection\n");
775 fail_union_operation (op); 884 fail_union_operation (op);
776 return GNUNET_SYSERR; 885 return GNUNET_SYSERR;
777 } 886 }
887
888
889 if ( (GNUNET_YES == op->spec->force_full) || (diff > op->state->initial_size / 2))
890 {
891 LOG (GNUNET_ERROR_TYPE_INFO,
892 "Sending full set (diff=%d, own set=%u)\n",
893 diff,
894 op->state->initial_size);
895 if (op->state->initial_size <= other_size)
896 {
897 send_full_set (op);
898 }
899 else
900 {
901 struct GNUNET_MQ_Envelope *ev;
902 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_REQUEST_FULL);
903 GNUNET_MQ_send (op->mq, ev);
904 }
905 }
906 else
907 {
908 if (GNUNET_OK !=
909 send_ibf (op,
910 get_order_from_difference (diff)))
911 {
912 /* Internal error, best we can do is shut the connection */
913 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
914 "Failed to send IBF, closing connection\n");
915 fail_union_operation (op);
916 return GNUNET_SYSERR;
917 }
918 }
919
778 return GNUNET_OK; 920 return GNUNET_OK;
779} 921}
780 922
@@ -1210,6 +1352,8 @@ maybe_finish (struct Operation *op)
1210 1352
1211/** 1353/**
1212 * Handle an element message from a remote peer. 1354 * Handle an element message from a remote peer.
1355 * Sent by the other peer either because we decoded an IBF and placed a demand,
1356 * or because the other peer switched to full set transmission.
1213 * 1357 *
1214 * @param cls the union operation 1358 * @param cls the union operation
1215 * @param mh the message 1359 * @param mh the message
@@ -1273,7 +1417,11 @@ handle_p2p_elements (void *cls,
1273 1, 1417 1,
1274 GNUNET_NO); 1418 GNUNET_NO);
1275 1419
1276 if (GNUNET_YES == op_has_element (op, &ee->element_hash)) 1420 op->state->received_total += 1;
1421
1422 struct KeyEntry *ke = op_get_element (op, &ee->element_hash);
1423
1424 if (NULL != ke)
1277 { 1425 {
1278 /* Got repeated element. Should not happen since 1426 /* Got repeated element. Should not happen since
1279 * we track demands. */ 1427 * we track demands. */
@@ -1281,13 +1429,15 @@ handle_p2p_elements (void *cls,
1281 "# repeated elements", 1429 "# repeated elements",
1282 1, 1430 1,
1283 GNUNET_NO); 1431 GNUNET_NO);
1432 ke->received = GNUNET_YES;
1284 GNUNET_free (ee); 1433 GNUNET_free (ee);
1285 } 1434 }
1286 else 1435 else
1287 { 1436 {
1288 LOG (GNUNET_ERROR_TYPE_DEBUG, 1437 LOG (GNUNET_ERROR_TYPE_DEBUG,
1289 "Registering new element from remote peer\n"); 1438 "Registering new element from remote peer\n");
1290 op_register_element (op, ee); 1439 op->state->received_fresh += 1;
1440 op_register_element (op, ee, GNUNET_YES);
1291 /* only send results immediately if the client wants it */ 1441 /* only send results immediately if the client wants it */
1292 switch (op->spec->result_mode) 1442 switch (op->spec->result_mode)
1293 { 1443 {
@@ -1304,11 +1454,112 @@ handle_p2p_elements (void *cls,
1304 } 1454 }
1305 } 1455 }
1306 1456
1457 if (op->state->received_total > 8 && op->state->received_fresh < op->state->received_total / 3)
1458 {
1459 /* The other peer gave us lots of old elements, there's something wrong. */
1460 GNUNET_break_op (0);
1461 fail_union_operation (op);
1462 return;
1463 }
1464
1307 maybe_finish (op); 1465 maybe_finish (op);
1308} 1466}
1309 1467
1310 1468
1311/** 1469/**
1470 * Handle an element message from a remote peer.
1471 *
1472 * @param cls the union operation
1473 * @param mh the message
1474 */
1475static void
1476handle_p2p_full_element (void *cls,
1477 const struct GNUNET_MessageHeader *mh)
1478{
1479 struct Operation *op = cls;
1480 struct ElementEntry *ee;
1481 const struct GNUNET_SET_ElementMessage *emsg;
1482 uint16_t element_size;
1483
1484 if (ntohs (mh->size) < sizeof (struct GNUNET_SET_ElementMessage))
1485 {
1486 GNUNET_break_op (0);
1487 fail_union_operation (op);
1488 return;
1489 }
1490
1491 emsg = (const struct GNUNET_SET_ElementMessage *) mh;
1492
1493 element_size = ntohs (mh->size) - sizeof (struct GNUNET_SET_ElementMessage);
1494 ee = GNUNET_malloc (sizeof (struct ElementEntry) + element_size);
1495 GNUNET_memcpy (&ee[1], &emsg[1], element_size);
1496 ee->element.size = element_size;
1497 ee->element.data = &ee[1];
1498 ee->element.element_type = ntohs (emsg->element_type);
1499 ee->remote = GNUNET_YES;
1500 GNUNET_SET_element_hash (&ee->element, &ee->element_hash);
1501
1502 LOG (GNUNET_ERROR_TYPE_DEBUG,
1503 "Got element (full diff, size %u, hash %s) from peer\n",
1504 (unsigned int) element_size,
1505 GNUNET_h2s (&ee->element_hash));
1506
1507 GNUNET_STATISTICS_update (_GSS_statistics,
1508 "# received elements",
1509 1,
1510 GNUNET_NO);
1511 GNUNET_STATISTICS_update (_GSS_statistics,
1512 "# exchanged elements",
1513 1,
1514 GNUNET_NO);
1515
1516 op->state->received_total += 1;
1517
1518 struct KeyEntry *ke = op_get_element (op, &ee->element_hash);
1519
1520 if (NULL != ke)
1521 {
1522 /* Got repeated element. Should not happen since
1523 * we track demands. */
1524 GNUNET_STATISTICS_update (_GSS_statistics,
1525 "# repeated elements",
1526 1,
1527 GNUNET_NO);
1528 ke->received = GNUNET_YES;
1529 GNUNET_free (ee);
1530 }
1531 else
1532 {
1533 LOG (GNUNET_ERROR_TYPE_DEBUG,
1534 "Registering new element from remote peer\n");
1535 op->state->received_fresh += 1;
1536 op_register_element (op, ee, GNUNET_YES);
1537 /* only send results immediately if the client wants it */
1538 switch (op->spec->result_mode)
1539 {
1540 case GNUNET_SET_RESULT_ADDED:
1541 send_client_element (op, &ee->element, GNUNET_SET_STATUS_OK);
1542 break;
1543 case GNUNET_SET_RESULT_SYMMETRIC:
1544 send_client_element (op, &ee->element, GNUNET_SET_STATUS_ADD_LOCAL);
1545 break;
1546 default:
1547 /* Result mode not supported, should have been caught earlier. */
1548 GNUNET_break (0);
1549 break;
1550 }
1551 }
1552
1553 if (op->state->received_total > 8 && op->state->received_fresh < op->state->received_total / 3)
1554 {
1555 /* The other peer gave us lots of old elements, there's something wrong. */
1556 GNUNET_break_op (0);
1557 fail_union_operation (op);
1558 return;
1559 }
1560}
1561
1562/**
1312 * Send offers (for GNUNET_Hash-es) in response 1563 * Send offers (for GNUNET_Hash-es) in response
1313 * to inquiries (for IBF_Key-s). 1564 * to inquiries (for IBF_Key-s).
1314 * 1565 *
@@ -1355,7 +1606,116 @@ handle_p2p_inquiry (void *cls,
1355 1606
1356 1607
1357/** 1608/**
1358 * FIXME 1609 * Iterator over hash map entries, called to
1610 * destroy the linked list of colliding ibf key entries.
1611 *
1612 * @param cls closure
1613 * @param key current key code
1614 * @param value value in the hash map
1615 * @return #GNUNET_YES if we should continue to iterate,
1616 * #GNUNET_NO if not.
1617 */
1618static int
1619send_missing_elements_iter (void *cls,
1620 uint32_t key,
1621 void *value)
1622{
1623 struct Operation *op = cls;
1624 struct KeyEntry *ke = value;
1625 struct GNUNET_MQ_Envelope *ev;
1626 struct GNUNET_SET_ElementMessage *emsg;
1627 struct ElementEntry *ee = ke->element;
1628
1629 if (GNUNET_YES == ke->received)
1630 return GNUNET_YES;
1631
1632 ev = GNUNET_MQ_msg_extra (emsg, ee->element.size, GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_ELEMENT);
1633 GNUNET_memcpy (&emsg[1], ee->element.data, ee->element.size);
1634 emsg->reserved = htons (0);
1635 emsg->element_type = htons (ee->element.element_type);
1636 GNUNET_MQ_send (op->mq, ev);
1637
1638 return GNUNET_YES;
1639}
1640
1641
1642/**
1643 * Handle a
1644 *
1645 * @parem cls closure, a set union operation
1646 * @param mh the demand message
1647 */
1648static void
1649handle_p2p_request_full (void *cls,
1650 const struct GNUNET_MessageHeader *mh)
1651{
1652 struct Operation *op = cls;
1653
1654 if (PHASE_EXPECT_IBF != op->state->phase)
1655 {
1656 fail_union_operation (op);
1657 GNUNET_break_op (0);
1658 return;
1659 }
1660
1661 // FIXME: we need to check that our set is larger than the
1662 // byzantine_lower_bound by some threshold
1663 send_full_set (op);
1664}
1665
1666
1667/**
1668 * Handle a "full done" message.
1669 *
1670 * @parem cls closure, a set union operation
1671 * @param mh the demand message
1672 */
1673static void
1674handle_p2p_full_done (void *cls,
1675 const struct GNUNET_MessageHeader *mh)
1676{
1677 struct Operation *op = cls;
1678
1679 if (PHASE_EXPECT_IBF == op->state->phase)
1680 {
1681 struct GNUNET_MQ_Envelope *ev;
1682
1683 LOG (GNUNET_ERROR_TYPE_DEBUG, "got FULL DONE, sending elements that other peer is missing\n");
1684
1685 /* send all the elements that did not come from the remote peer */
1686 GNUNET_CONTAINER_multihashmap32_iterate (op->state->key_to_element,
1687 &send_missing_elements_iter,
1688 op);
1689
1690 ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE);
1691 GNUNET_MQ_send (op->mq, ev);
1692 op->state->phase = PHASE_DONE;
1693
1694 /* we now wait until the other peer shuts the tunnel down*/
1695 }
1696 else if (PHASE_FULL_SENDING == op->state->phase)
1697 {
1698 LOG (GNUNET_ERROR_TYPE_DEBUG, "got FULL DONE, finishing\n");
1699 /* We sent the full set, and got the response for that. We're done. */
1700 op->state->phase = PHASE_DONE;
1701 send_done_and_destroy (op);
1702 }
1703 else
1704 {
1705 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "handle full done phase is %u\n", (unsigned) op->state->phase);
1706 GNUNET_break_op (0);
1707 fail_union_operation (op);
1708 return;
1709 }
1710}
1711
1712
1713/**
1714 * Handle a demand by the other peer for elements based on a list
1715 * of GNUNET_HashCode-s.
1716 *
1717 * @parem cls closure, a set union operation
1718 * @param mh the demand message
1359 */ 1719 */
1360static void 1720static void
1361handle_p2p_demand (void *cls, 1721handle_p2p_demand (void *cls,
@@ -1607,6 +1967,9 @@ union_evaluate (struct Operation *op,
1607 else 1967 else
1608 LOG (GNUNET_ERROR_TYPE_DEBUG, 1968 LOG (GNUNET_ERROR_TYPE_DEBUG,
1609 "sent op request without context message\n"); 1969 "sent op request without context message\n");
1970
1971 op->state->initial_size = GNUNET_CONTAINER_multihashmap_size (op->spec->set->content->elements);
1972 initialize_key_to_element (op);
1610} 1973}
1611 1974
1612 1975
@@ -1636,6 +1999,8 @@ union_accept (struct Operation *op)
1636 op->state->se = strata_estimator_dup (op->spec->set->state->se); 1999 op->state->se = strata_estimator_dup (op->spec->set->state->se);
1637 op->state->demanded_hashes = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); 2000 op->state->demanded_hashes = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
1638 op->state->salt_receive = op->state->salt_send = 42; 2001 op->state->salt_receive = op->state->salt_send = 42;
2002 op->state->initial_size = GNUNET_CONTAINER_multihashmap_size (op->spec->set->content->elements);
2003 initialize_key_to_element (op);
1639 /* kick off the operation */ 2004 /* kick off the operation */
1640 send_strata_estimator (op); 2005 send_strata_estimator (op);
1641} 2006}
@@ -1743,6 +2108,9 @@ union_handle_p2p_message (struct Operation *op,
1743 case GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS: 2108 case GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS:
1744 handle_p2p_elements (op, mh); 2109 handle_p2p_elements (op, mh);
1745 break; 2110 break;
2111 case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_ELEMENT:
2112 handle_p2p_full_element (op, mh);
2113 break;
1746 case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_INQUIRY: 2114 case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_INQUIRY:
1747 handle_p2p_inquiry (op, mh); 2115 handle_p2p_inquiry (op, mh);
1748 break; 2116 break;
@@ -1755,6 +2123,12 @@ union_handle_p2p_message (struct Operation *op,
1755 case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DEMAND: 2123 case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DEMAND:
1756 handle_p2p_demand (op, mh); 2124 handle_p2p_demand (op, mh);
1757 break; 2125 break;
2126 case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_FULL_DONE:
2127 handle_p2p_full_done (op, mh);
2128 break;
2129 case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_REQUEST_FULL:
2130 handle_p2p_request_full (op, mh);
2131 break;
1758 default: 2132 default:
1759 /* Something wrong with cadet's message handlers? */ 2133 /* Something wrong with cadet's message handlers? */
1760 GNUNET_assert (0); 2134 GNUNET_assert (0);
diff --git a/src/set/gnunet-set-profiler.c b/src/set/gnunet-set-profiler.c
index f89817ff5..971d9746a 100644
--- a/src/set/gnunet-set-profiler.c
+++ b/src/set/gnunet-set-profiler.c
@@ -58,6 +58,10 @@ static struct GNUNET_PeerIdentity local_peer;
58 58
59static struct GNUNET_SET_ListenHandle *set_listener; 59static struct GNUNET_SET_ListenHandle *set_listener;
60 60
61static int byzantine;
62static int force_delta;
63static int force_full;
64
61/** 65/**
62 * Handle to the statistics service. 66 * Handle to the statistics service.
63 */ 67 */
@@ -215,6 +219,10 @@ set_listen_cb (void *cls,
215 const struct GNUNET_MessageHeader *context_msg, 219 const struct GNUNET_MessageHeader *context_msg,
216 struct GNUNET_SET_Request *request) 220 struct GNUNET_SET_Request *request)
217{ 221{
222 /* max. 2 options plus terminator */
223 struct GNUNET_SET_Option opts[3] = {0};
224 unsigned int n_opts = 0;
225
218 if (NULL == request) 226 if (NULL == request)
219 { 227 {
220 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 228 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -224,8 +232,24 @@ set_listen_cb (void *cls,
224 GNUNET_assert (NULL == info2.oh); 232 GNUNET_assert (NULL == info2.oh);
225 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 233 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
226 "set listen cb called\n"); 234 "set listen cb called\n");
235 if (byzantine)
236 {
237 opts[n_opts++] = (struct GNUNET_SET_Option) { .type = GNUNET_SET_OPTION_BYZANTINE };
238 }
239 GNUNET_assert (!(force_full && force_delta));
240 if (force_full)
241 {
242 opts[n_opts++] = (struct GNUNET_SET_Option) { .type = GNUNET_SET_OPTION_FORCE_FULL };
243 }
244 if (force_delta)
245 {
246 opts[n_opts++] = (struct GNUNET_SET_Option) { .type = GNUNET_SET_OPTION_FORCE_DELTA };
247 }
248
249 opts[n_opts].type = 0;
227 info2.oh = GNUNET_SET_accept (request, GNUNET_SET_RESULT_SYMMETRIC, 250 info2.oh = GNUNET_SET_accept (request, GNUNET_SET_RESULT_SYMMETRIC,
228 set_result_cb, &info2); 251 opts,
252 set_result_cb, &info2);
229 GNUNET_SET_commit (info2.oh, info2.set); 253 GNUNET_SET_commit (info2.oh, info2.set);
230} 254}
231 255
@@ -291,6 +315,9 @@ run (void *cls,
291{ 315{
292 unsigned int i; 316 unsigned int i;
293 struct GNUNET_HashCode hash; 317 struct GNUNET_HashCode hash;
318 /* max. 2 options plus terminator */
319 struct GNUNET_SET_Option opts[3] = {0};
320 unsigned int n_opts = 0;
294 321
295 config = cfg; 322 config = cfg;
296 323
@@ -350,8 +377,26 @@ run (void *cls,
350 set_listener = GNUNET_SET_listen (config, GNUNET_SET_OPERATION_UNION, 377 set_listener = GNUNET_SET_listen (config, GNUNET_SET_OPERATION_UNION,
351 &app_id, set_listen_cb, NULL); 378 &app_id, set_listen_cb, NULL);
352 379
380
381 if (byzantine)
382 {
383 opts[n_opts++] = (struct GNUNET_SET_Option) { .type = GNUNET_SET_OPTION_BYZANTINE };
384 }
385 GNUNET_assert (!(force_full && force_delta));
386 if (force_full)
387 {
388 opts[n_opts++] = (struct GNUNET_SET_Option) { .type = GNUNET_SET_OPTION_FORCE_FULL };
389 }
390 if (force_delta)
391 {
392 opts[n_opts++] = (struct GNUNET_SET_Option) { .type = GNUNET_SET_OPTION_FORCE_DELTA };
393 }
394
395 opts[n_opts].type = 0;
396
353 info1.oh = GNUNET_SET_prepare (&local_peer, &app_id, NULL, 397 info1.oh = GNUNET_SET_prepare (&local_peer, &app_id, NULL,
354 GNUNET_SET_RESULT_SYMMETRIC, 398 GNUNET_SET_RESULT_SYMMETRIC,
399 opts,
355 set_result_cb, &info1); 400 set_result_cb, &info1);
356 GNUNET_SET_commit (info1.oh, info1.set); 401 GNUNET_SET_commit (info1.oh, info1.set);
357 GNUNET_SET_destroy (info1.set); 402 GNUNET_SET_destroy (info1.set);
@@ -380,6 +425,15 @@ main (int argc, char **argv)
380 { 'B', "num-second", NULL, 425 { 'B', "num-second", NULL,
381 gettext_noop ("number of values"), 426 gettext_noop ("number of values"),
382 GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_b }, 427 GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_b },
428 { 'b', "byzantine", NULL,
429 gettext_noop ("use byzantine mode"),
430 GNUNET_NO, &GNUNET_GETOPT_set_one, &byzantine },
431 { 'f', "force-full", NULL,
432 gettext_noop ("force sending full set"),
433 GNUNET_NO, &GNUNET_GETOPT_set_uint, &force_full },
434 { 'd', "force-delta", NULL,
435 gettext_noop ("number delta operation"),
436 GNUNET_NO, &GNUNET_GETOPT_set_uint, &force_delta },
383 { 'C', "num-common", NULL, 437 { 'C', "num-common", NULL,
384 gettext_noop ("number of values"), 438 gettext_noop ("number of values"),
385 GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_c }, 439 GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_c },
diff --git a/src/set/set.h b/src/set/set.h
index f31216cb8..207f098bc 100644
--- a/src/set/set.h
+++ b/src/set/set.h
@@ -102,6 +102,30 @@ struct GNUNET_SET_AcceptMessage
102 * See `enum GNUNET_SET_ResultMode`. 102 * See `enum GNUNET_SET_ResultMode`.
103 */ 103 */
104 uint32_t result_mode GNUNET_PACKED; 104 uint32_t result_mode GNUNET_PACKED;
105
106 /**
107 * Always use delta operation instead of sending full sets,
108 * even it it's less efficient.
109 */
110 uint8_t force_delta;
111
112 /**
113 * Always send full sets, even if delta operations would
114 * be more efficient.
115 */
116 uint8_t force_full;
117
118 /**
119 * #GNUNET_YES to fail operations where Byzantine faults
120 * are suspected
121 */
122 uint8_t byzantine;
123
124 /**
125 * Lower bound for the set size, used only when
126 * byzantine mode is enabled.
127 */
128 uint8_t byzantine_lower_bound;
105}; 129};
106 130
107 131
@@ -184,6 +208,30 @@ struct GNUNET_SET_EvaluateMessage
184 */ 208 */
185 uint32_t request_id GNUNET_PACKED; 209 uint32_t request_id GNUNET_PACKED;
186 210
211 /**
212 * Always use delta operation instead of sending full sets,
213 * even it it's less efficient.
214 */
215 uint8_t force_delta;
216
217 /**
218 * Always send full sets, even if delta operations would
219 * be more efficient.
220 */
221 uint8_t force_full;
222
223 /**
224 * #GNUNET_YES to fail operations where Byzantine faults
225 * are suspected
226 */
227 uint8_t byzantine;
228
229 /**
230 * Lower bound for the set size, used only when
231 * byzantine mode is enabled.
232 */
233 uint8_t byzantine_lower_bound;
234
187 /* rest: context message, that is, application-specific 235 /* rest: context message, that is, application-specific
188 message to convince listener to pick up */ 236 message to convince listener to pick up */
189}; 237};
diff --git a/src/set/set_api.c b/src/set/set_api.c
index baeee6da0..2b09725e8 100644
--- a/src/set/set_api.c
+++ b/src/set/set_api.c
@@ -766,12 +766,14 @@ GNUNET_SET_prepare (const struct GNUNET_PeerIdentity *other_peer,
766 const struct GNUNET_HashCode *app_id, 766 const struct GNUNET_HashCode *app_id,
767 const struct GNUNET_MessageHeader *context_msg, 767 const struct GNUNET_MessageHeader *context_msg,
768 enum GNUNET_SET_ResultMode result_mode, 768 enum GNUNET_SET_ResultMode result_mode,
769 struct GNUNET_SET_Option options[],
769 GNUNET_SET_ResultIterator result_cb, 770 GNUNET_SET_ResultIterator result_cb,
770 void *result_cls) 771 void *result_cls)
771{ 772{
772 struct GNUNET_MQ_Envelope *mqm; 773 struct GNUNET_MQ_Envelope *mqm;
773 struct GNUNET_SET_OperationHandle *oh; 774 struct GNUNET_SET_OperationHandle *oh;
774 struct GNUNET_SET_EvaluateMessage *msg; 775 struct GNUNET_SET_EvaluateMessage *msg;
776 struct GNUNET_SET_Option *opt;
775 777
776 LOG (GNUNET_ERROR_TYPE_DEBUG, 778 LOG (GNUNET_ERROR_TYPE_DEBUG,
777 "Client prepares set operation (%d)\n", 779 "Client prepares set operation (%d)\n",
@@ -785,6 +787,25 @@ GNUNET_SET_prepare (const struct GNUNET_PeerIdentity *other_peer,
785 msg->app_id = *app_id; 787 msg->app_id = *app_id;
786 msg->result_mode = htonl (result_mode); 788 msg->result_mode = htonl (result_mode);
787 msg->target_peer = *other_peer; 789 msg->target_peer = *other_peer;
790 for (opt = options; opt->type != 0; opt++)
791 {
792 switch (opt->type)
793 {
794 case GNUNET_SET_OPTION_BYZANTINE:
795 msg->byzantine = GNUNET_YES;
796 msg->byzantine_lower_bound = opt->v.num;
797 break;
798 case GNUNET_SET_OPTION_FORCE_FULL:
799 msg->force_full = GNUNET_YES;
800 break;
801 case GNUNET_SET_OPTION_FORCE_DELTA:
802 msg->force_delta = GNUNET_YES;
803 break;
804 default:
805 LOG (GNUNET_ERROR_TYPE_ERROR,
806 "Option with type %d not recognized\n", (int) opt->type);
807 }
808 }
788 oh->conclude_mqm = mqm; 809 oh->conclude_mqm = mqm;
789 oh->request_id_addr = &msg->request_id; 810 oh->request_id_addr = &msg->request_id;
790 811
@@ -1006,6 +1027,7 @@ GNUNET_SET_listen_cancel (struct GNUNET_SET_ListenHandle *lh)
1006struct GNUNET_SET_OperationHandle * 1027struct GNUNET_SET_OperationHandle *
1007GNUNET_SET_accept (struct GNUNET_SET_Request *request, 1028GNUNET_SET_accept (struct GNUNET_SET_Request *request,
1008 enum GNUNET_SET_ResultMode result_mode, 1029 enum GNUNET_SET_ResultMode result_mode,
1030 struct GNUNET_SET_Option options[],
1009 GNUNET_SET_ResultIterator result_cb, 1031 GNUNET_SET_ResultIterator result_cb,
1010 void *result_cls) 1032 void *result_cls)
1011{ 1033{
diff --git a/src/set/test_set.conf b/src/set/test_set.conf
index 69e7f5c52..30ccbde55 100644
--- a/src/set/test_set.conf
+++ b/src/set/test_set.conf
@@ -5,7 +5,7 @@ GNUNET_TEST_HOME = /tmp/test-gnunet-set/
5 5
6[set] 6[set]
7AUTOSTART = YES 7AUTOSTART = YES
8# PREFIX = valgrind 8PREFIX = valgrind
9#PREFIX = valgrind --leak-check=full 9#PREFIX = valgrind --leak-check=full
10#PREFIX = gdbserver :1234 10#PREFIX = gdbserver :1234
11OPTIONS = -L INFO 11OPTIONS = -L INFO
diff --git a/src/set/test_set_api.c b/src/set/test_set_api.c
index 21af45f8a..4bc6bd1c3 100644
--- a/src/set/test_set_api.c
+++ b/src/set/test_set_api.c
@@ -149,6 +149,7 @@ listen_cb (void *cls,
149 listen_handle = NULL; 149 listen_handle = NULL;
150 oh2 = GNUNET_SET_accept (request, 150 oh2 = GNUNET_SET_accept (request,
151 GNUNET_SET_RESULT_ADDED, 151 GNUNET_SET_RESULT_ADDED,
152 (struct GNUNET_SET_Option[]) { 0 },
152 &result_cb_set2, 153 &result_cb_set2,
153 NULL); 154 NULL);
154 GNUNET_SET_commit (oh2, 155 GNUNET_SET_commit (oh2,
@@ -179,6 +180,7 @@ start (void *cls)
179 &app_id, 180 &app_id,
180 &context_msg, 181 &context_msg,
181 GNUNET_SET_RESULT_ADDED, 182 GNUNET_SET_RESULT_ADDED,
183 (struct GNUNET_SET_Option[]) { 0 },
182 &result_cb_set1, 184 &result_cb_set1,
183 NULL); 185 NULL);
184 GNUNET_SET_commit (oh1, 186 GNUNET_SET_commit (oh1,
@@ -378,6 +380,7 @@ run (void *cls,
378 &app_id, 380 &app_id,
379 NULL, 381 NULL,
380 GNUNET_SET_RESULT_ADDED, 382 GNUNET_SET_RESULT_ADDED,
383 (struct GNUNET_SET_Option[]) { 0 },
381 NULL, 384 NULL,
382 NULL); 385 NULL);
383 386
diff --git a/src/set/test_set_intersection_result_full.c b/src/set/test_set_intersection_result_full.c
index b2d6ce8a9..cbe1ce149 100644
--- a/src/set/test_set_intersection_result_full.c
+++ b/src/set/test_set_intersection_result_full.c
@@ -133,6 +133,7 @@ listen_cb (void *cls,
133 listen_handle = NULL; 133 listen_handle = NULL;
134 oh2 = GNUNET_SET_accept (request, 134 oh2 = GNUNET_SET_accept (request,
135 GNUNET_SET_RESULT_FULL, 135 GNUNET_SET_RESULT_FULL,
136 (struct GNUNET_SET_Option[]) { 0 },
136 &result_cb_set2, 137 &result_cb_set2,
137 NULL); 138 NULL);
138 GNUNET_SET_commit (oh2, 139 GNUNET_SET_commit (oh2,
@@ -163,6 +164,7 @@ start (void *cls)
163 &app_id, 164 &app_id,
164 &context_msg, 165 &context_msg,
165 GNUNET_SET_RESULT_FULL, 166 GNUNET_SET_RESULT_FULL,
167 (struct GNUNET_SET_Option[]) { 0 },
166 &result_cb_set1, 168 &result_cb_set1,
167 NULL); 169 NULL);
168 GNUNET_SET_commit (oh1, 170 GNUNET_SET_commit (oh1,
diff --git a/src/set/test_set_union_result_symmetric.c b/src/set/test_set_union_result_symmetric.c
index ab191a34a..8dff40ec0 100644
--- a/src/set/test_set_union_result_symmetric.c
+++ b/src/set/test_set_union_result_symmetric.c
@@ -184,6 +184,7 @@ listen_cb (void *cls,
184 listen_handle = NULL; 184 listen_handle = NULL;
185 oh2 = GNUNET_SET_accept (request, 185 oh2 = GNUNET_SET_accept (request,
186 GNUNET_SET_RESULT_SYMMETRIC, 186 GNUNET_SET_RESULT_SYMMETRIC,
187 (struct GNUNET_SET_Option[]) { 0 },
187 &result_cb_set2, 188 &result_cb_set2,
188 NULL); 189 NULL);
189 GNUNET_SET_commit (oh2, 190 GNUNET_SET_commit (oh2,
@@ -212,6 +213,7 @@ start (void *cls)
212 &app_id, 213 &app_id,
213 &context_msg, 214 &context_msg,
214 GNUNET_SET_RESULT_SYMMETRIC, 215 GNUNET_SET_RESULT_SYMMETRIC,
216 (struct GNUNET_SET_Option[]) { 0 },
215 &result_cb_set1, NULL); 217 &result_cb_set1, NULL);
216 GNUNET_SET_commit (oh1, set1); 218 GNUNET_SET_commit (oh1, set1);
217} 219}
diff --git a/src/testing/testing.c b/src/testing/testing.c
index 043bdd7d2..bab7976ea 100644
--- a/src/testing/testing.c
+++ b/src/testing/testing.c
@@ -1633,7 +1633,9 @@ GNUNET_TESTING_service_run (const char *testdir,
1633 char *binary; 1633 char *binary;
1634 char *libexec_binary; 1634 char *libexec_binary;
1635 1635
1636 GNUNET_log_setup (testdir, "WARNING", NULL); 1636 GNUNET_log_setup (testdir,
1637 "WARNING",
1638 NULL);
1637 system = GNUNET_TESTING_system_create (testdir, "127.0.0.1", NULL, NULL); 1639 system = GNUNET_TESTING_system_create (testdir, "127.0.0.1", NULL, NULL);
1638 if (NULL == system) 1640 if (NULL == system)
1639 return 1; 1641 return 1;
diff --git a/src/transport/gnunet-service-transport_neighbours.c b/src/transport/gnunet-service-transport_neighbours.c
index 3952a728e..bbda715a2 100644
--- a/src/transport/gnunet-service-transport_neighbours.c
+++ b/src/transport/gnunet-service-transport_neighbours.c
@@ -1150,17 +1150,18 @@ set_incoming_quota (struct NeighbourMapEntry *n,
1150 sqm.header.size = htons (sizeof (struct GNUNET_ATS_SessionQuotaMessage)); 1150 sqm.header.size = htons (sizeof (struct GNUNET_ATS_SessionQuotaMessage));
1151 sqm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_QUOTA); 1151 sqm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_QUOTA);
1152 sqm.quota = quota.value__; 1152 sqm.quota = quota.value__;
1153 (void) send_with_session (n, 1153 if (NULL != n->primary_address.session)
1154 &sqm, 1154 (void) send_with_session (n,
1155 sizeof (sqm), 1155 &sqm,
1156 UINT32_MAX - 1, 1156 sizeof (sqm),
1157 GNUNET_TIME_UNIT_FOREVER_REL, 1157 UINT32_MAX - 1,
1158 GNUNET_NO, 1158 GNUNET_TIME_UNIT_FOREVER_REL,
1159 NULL, NULL); 1159 GNUNET_NO,
1160 NULL, NULL);
1160 return; 1161 return;
1161 } 1162 }
1162 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1163 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1163 "Disconnecting peer `%4s' due to SET_QUOTA\n", 1164 "Disconnecting peer `%s' due to SET_QUOTA\n",
1164 GNUNET_i2s (&n->id)); 1165 GNUNET_i2s (&n->id));
1165 if (GNUNET_YES == test_connected (n)) 1166 if (GNUNET_YES == test_connected (n))
1166 GNUNET_STATISTICS_update (GST_stats, 1167 GNUNET_STATISTICS_update (GST_stats,
diff --git a/src/util/mq.c b/src/util/mq.c
index a8216d964..71619bda4 100644
--- a/src/util/mq.c
+++ b/src/util/mq.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2012-2014 GNUnet e.V. 3 Copyright (C) 2012-2017 GNUnet e.V.
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
@@ -362,6 +362,7 @@ GNUNET_MQ_send (struct GNUNET_MQ_Handle *mq,
362 GNUNET_assert (NULL == ev->parent_queue); 362 GNUNET_assert (NULL == ev->parent_queue);
363 363
364 mq->queue_length++; 364 mq->queue_length++;
365 GNUNET_break (mq->queue_length < 10000); /* This would seem like a bug... */
365 ev->parent_queue = mq; 366 ev->parent_queue = mq;
366 /* is the implementation busy? queue it! */ 367 /* is the implementation busy? queue it! */
367 if ( (NULL != mq->current_envelope) || 368 if ( (NULL != mq->current_envelope) ||
diff --git a/src/util/os_installation.c b/src/util/os_installation.c
index caceeea0c..1226c5966 100644
--- a/src/util/os_installation.c
+++ b/src/util/os_installation.c
@@ -823,9 +823,13 @@ GNUNET_OS_check_helper_binary (const char *binary,
823#ifdef MINGW 823#ifdef MINGW
824 char *binaryexe; 824 char *binaryexe;
825 825
826 GNUNET_asprintf (&binaryexe, "%s.exe", binary); 826 GNUNET_asprintf (&binaryexe,
827 if ( (GNUNET_YES == GNUNET_STRINGS_path_is_absolute (binaryexe, GNUNET_NO, 827 "%s.exe",
828 NULL, NULL)) || 828 binary);
829 if ( (GNUNET_YES ==
830 GNUNET_STRINGS_path_is_absolute (binaryexe,
831 GNUNET_NO,
832 NULL, NULL)) ||
829 (0 == strncmp (binary, "./", 2)) ) 833 (0 == strncmp (binary, "./", 2)) )
830 p = GNUNET_strdup (binaryexe); 834 p = GNUNET_strdup (binaryexe);
831 else 835 else
@@ -840,16 +844,24 @@ GNUNET_OS_check_helper_binary (const char *binary,
840 } 844 }
841 GNUNET_free (binaryexe); 845 GNUNET_free (binaryexe);
842#else 846#else
843 if ( (GNUNET_YES == GNUNET_STRINGS_path_is_absolute (binary, GNUNET_NO, 847 if ( (GNUNET_YES ==
844 NULL, NULL)) || 848 GNUNET_STRINGS_path_is_absolute (binary,
849 GNUNET_NO,
850 NULL,
851 NULL)) ||
845 (0 == strncmp (binary, "./", 2)) ) 852 (0 == strncmp (binary, "./", 2)) )
853 {
846 p = GNUNET_strdup (binary); 854 p = GNUNET_strdup (binary);
855 }
847 else 856 else
848 { 857 {
849 p = get_path_from_PATH (binary); 858 p = get_path_from_PATH (binary);
850 if (NULL != p) 859 if (NULL != p)
851 { 860 {
852 GNUNET_asprintf (&pf, "%s/%s", p, binary); 861 GNUNET_asprintf (&pf,
862 "%s/%s",
863 p,
864 binary);
853 GNUNET_free (p); 865 GNUNET_free (p);
854 p = pf; 866 p = pf;
855 } 867 }
@@ -862,9 +874,12 @@ GNUNET_OS_check_helper_binary (const char *binary,
862 binary); 874 binary);
863 return GNUNET_SYSERR; 875 return GNUNET_SYSERR;
864 } 876 }
865 if (0 != ACCESS (p, X_OK)) 877 if (0 != ACCESS (p,
878 X_OK))
866 { 879 {
867 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "access", p); 880 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING,
881 "access",
882 p);
868 GNUNET_free (p); 883 GNUNET_free (p);
869 return GNUNET_SYSERR; 884 return GNUNET_SYSERR;
870 } 885 }
@@ -873,22 +888,30 @@ GNUNET_OS_check_helper_binary (const char *binary,
873 { 888 {
874 /* as we run as root, we don't insist on SUID */ 889 /* as we run as root, we don't insist on SUID */
875 GNUNET_free (p); 890 GNUNET_free (p);
876 return GNUNET_OK; 891 return GNUNET_YES;
877 } 892 }
878#endif 893#endif
879 if (0 != STAT (p, &statbuf)) 894 if (0 != STAT (p,
895 &statbuf))
880 { 896 {
881 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", p); 897 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING,
898 "stat",
899 p);
882 GNUNET_free (p); 900 GNUNET_free (p);
883 return GNUNET_SYSERR; 901 return GNUNET_SYSERR;
884 } 902 }
885 if (check_suid){ 903 if (check_suid)
904 {
886#ifndef MINGW 905#ifndef MINGW
887 if ((0 != (statbuf.st_mode & S_ISUID)) && (0 == statbuf.st_uid)) 906 if ( (0 != (statbuf.st_mode & S_ISUID)) &&
907 (0 == statbuf.st_uid) )
888 { 908 {
889 GNUNET_free (p); 909 GNUNET_free (p);
890 return GNUNET_YES; 910 return GNUNET_YES;
891 } 911 }
912 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
913 _("Binary `%s' exists, but is not SUID\n"),
914 p);
892 /* binary exists, but not SUID */ 915 /* binary exists, but not SUID */
893#else 916#else
894 STARTUPINFO start; 917 STARTUPINFO start;
diff --git a/src/util/service_new.c b/src/util/service_new.c
index a832b070c..987fb1c3b 100644
--- a/src/util/service_new.c
+++ b/src/util/service_new.c
@@ -1996,8 +1996,9 @@ service_mq_send (struct GNUNET_MQ_Handle *mq,
1996{ 1996{
1997 struct GNUNET_SERVICE_Client *client = impl_state; 1997 struct GNUNET_SERVICE_Client *client = impl_state;
1998 1998
1999 if (NULL != client->drop_task)
2000 return; /* we're going down right now, do not try to send */
1999 GNUNET_assert (NULL == client->send_task); 2001 GNUNET_assert (NULL == client->send_task);
2000 GNUNET_assert (NULL == client->drop_task);
2001 client->msg = msg; 2002 client->msg = msg;
2002 client->msg_pos = 0; 2003 client->msg_pos = 0;
2003 client->send_task 2004 client->send_task
@@ -2466,6 +2467,10 @@ finish_client_drop (void *cls)
2466 struct GNUNET_SERVICE_Client *c = cls; 2467 struct GNUNET_SERVICE_Client *c = cls;
2467 struct GNUNET_SERVICE_Handle *sh = c->sh; 2468 struct GNUNET_SERVICE_Handle *sh = c->sh;
2468 2469
2470 c->drop_task = NULL;
2471 GNUNET_assert (NULL == c->send_task);
2472 GNUNET_assert (NULL == c->recv_task);
2473 GNUNET_assert (NULL == c->warn_task);
2469 GNUNET_MST_destroy (c->mst); 2474 GNUNET_MST_destroy (c->mst);
2470 GNUNET_MQ_destroy (c->mq); 2475 GNUNET_MQ_destroy (c->mq);
2471 if (GNUNET_NO == c->persist) 2476 if (GNUNET_NO == c->persist)