aboutsummaryrefslogtreecommitdiff
path: root/src/exit
diff options
context:
space:
mode:
Diffstat (limited to 'src/exit')
-rw-r--r--src/exit/.gitignore2
-rw-r--r--src/exit/Makefile.am38
-rw-r--r--src/exit/exit.conf68
-rw-r--r--src/exit/exit.h298
-rw-r--r--src/exit/gnunet-daemon-exit.c4125
-rw-r--r--src/exit/gnunet-helper-exit.c859
6 files changed, 0 insertions, 5390 deletions
diff --git a/src/exit/.gitignore b/src/exit/.gitignore
deleted file mode 100644
index 9b75bba9a..000000000
--- a/src/exit/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
1gnunet-helper-exit
2gnunet-daemon-exit
diff --git a/src/exit/Makefile.am b/src/exit/Makefile.am
deleted file mode 100644
index c0323d0d6..000000000
--- a/src/exit/Makefile.am
+++ /dev/null
@@ -1,38 +0,0 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4if USE_COVERAGE
5 AM_CFLAGS = --coverage -O0
6endif
7
8pkgcfgdir= $(pkgdatadir)/config.d/
9
10libexecdir= $(pkglibdir)/libexec/
11
12plugindir = $(libdir)/gnunet
13
14dist_pkgcfg_DATA = \
15 exit.conf
16
17if LINUX
18EXITBIN = gnunet-helper-exit
19endif
20
21
22libexec_PROGRAMS = \
23 gnunet-daemon-exit \
24 $(EXITBIN)
25
26
27gnunet_helper_exit_SOURCES = \
28 gnunet-helper-exit.c
29
30gnunet_daemon_exit_SOURCES = \
31 gnunet-daemon-exit.c exit.h
32gnunet_daemon_exit_LDADD = \
33 $(top_builddir)/src/dht/libgnunetdht.la \
34 $(top_builddir)/src/statistics/libgnunetstatistics.la \
35 $(top_builddir)/src/util/libgnunetutil.la \
36 $(top_builddir)/src/cadet/libgnunetcadet.la \
37 $(top_builddir)/src/regex/libgnunetregex.la \
38 $(GN_LIBINTL)
diff --git a/src/exit/exit.conf b/src/exit/exit.conf
deleted file mode 100644
index 829c5bf80..000000000
--- a/src/exit/exit.conf
+++ /dev/null
@@ -1,68 +0,0 @@
1[exit]
2BINARY = gnunet-daemon-exit
3
4# IPv6 address for the TUN interface (must be changed as this
5# must be within the global IPv6 range of your system!)
6IPV6ADDR = 2001:DB8::1
7
8# Prefix for our IPv6 subnet on the TUN interface.
9IPV6PREFIX = 64
10
11# IPv4 address to use on our TUN interface (may need to be
12# changed to avoid conflicts with existing addresses on your system).
13# Use RFC 3927-style link-local address
14IPV4ADDR = 169.254.86.1
15
16# Netmask for the IPv4 subnet on the TUN interface.
17IPV4MASK = 255.255.255.0
18
19# IPv4 networks to which we are allowed to exit.
20# The format is "(network[/netmask][:[!]SPORT-DPORT];)*"
21EXIT_RANGE_IPV4_POLICY = 0.0.0.0/0:!25;
22
23# IPv6 networks to which we are allowed to exit.
24# The format is "(network[/netmask][:[!]SPORT-DPORT];)*"
25EXIT_RANGE_IPV6_POLICY = ::/0:!25;
26
27# Not a service, tell ARM no binding!
28NOARMBIND = YES
29
30# Name of the (virtual) tunnel interface the exit daemon will manage
31TUN_IFNAME = exit-gnunet
32
33# Name of the "real" interface that IPv4 traffic from this system will
34# leave from; this is the name of the interface where we need to
35# enable NAT on postrouting (typically something like 'eth0' or 'eth1'
36# or 'wlan0'). Not needed if EXIT_IPv4 is disabled AND if all
37# offered services run on 'localhost'. In this case, the value
38# of the option can instead be set to "%" (to not enable NAT on any
39# interface).
40EXIT_IFNAME = eth0
41
42# Set this to YES to allow exiting this system via IPv4 to the Internet
43EXIT_IPV4 = NO
44
45# Set this to YES to allow exiting this system via IPv6 to the Internet
46EXIT_IPV6 = NO
47
48# This option should be set to YES to allow the DNS service to
49# perform lookups against the locally configured DNS resolver.
50# (set to "NO" if no normal ISP is locally available and thus
51# requests for normal ".com"/".org"/etc. must be routed via
52# the GNUnet VPN (the GNUNET PT daemon then needs to be configured
53# to intercept and route DNS queries via cadet).
54# Set this to YES to allow using this system for DNS queries.
55EXIT_DNS = NO
56
57# Set this to an IPv4 or IPv6 address of a DNS resolver to use for DNS queries
58DNS_RESOLVER = 8.8.8.8
59
60# For IPv4-services offered by this peer, we need to at least enable IPv4
61ENABLE_IPV4 = YES
62
63# For IPv6-services offered by this peer, we need to at least enable IPv6
64ENABLE_IPV6 = YES
65
66
67# Maximum number of concurrent connections this exit supports.
68MAX_CONNECTIONS = 256
diff --git a/src/exit/exit.h b/src/exit/exit.h
deleted file mode 100644
index 41dad6246..000000000
--- a/src/exit/exit.h
+++ /dev/null
@@ -1,298 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012 Christian Grothoff
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file exit/exit.h
23 * @brief format for cadet messages exchanged between VPN service and exit daemon
24 * @author Christian Grothoff
25 */
26#ifndef EXIT_H
27#define EXIT_H
28
29#include "gnunet_util_lib.h"
30
31GNUNET_NETWORK_STRUCT_BEGIN
32
33/**
34 * Message send via cadet to an exit daemon to initiate forwarding of
35 * TCP data to a local service.
36 */
37struct GNUNET_EXIT_TcpServiceStartMessage
38{
39 /**
40 * Type is #GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START
41 */
42 struct GNUNET_MessageHeader header;
43
44 /**
45 * Always 0.
46 */
47 uint32_t reserved GNUNET_PACKED;
48
49 /**
50 * Skeleton of the TCP header to send. Port numbers are to
51 * be replaced and the checksum may be updated as necessary.
52 */
53 struct GNUNET_TUN_TcpHeader tcp_header;
54
55 /* followed by TCP payload */
56};
57
58
59/**
60 * Message send via cadet to an exit daemon to initiate forwarding of
61 * TCP data to the Internet.
62 */
63struct GNUNET_EXIT_TcpInternetStartMessage
64{
65 /**
66 * Type is #GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START
67 */
68 struct GNUNET_MessageHeader header;
69
70 /**
71 * Address family, AF_INET or AF_INET6, in network byte order.
72 */
73 int32_t af GNUNET_PACKED;
74
75 /**
76 * Skeleton of the TCP header to send. Port numbers are to
77 * be replaced and the checksum may be updated as necessary.
78 */
79 struct GNUNET_TUN_TcpHeader tcp_header;
80
81 /* followed by IP address of the destination; either
82 'struct in_addr' or 'struct in6_addr', depending on af */
83
84 /* followed by TCP payload */
85};
86
87
88/**
89 * Message send via cadet between VPN and entry and an exit daemon to
90 * transmit TCP data between the VPN entry and an exit session. This
91 * format is used for both Internet-exits and service-exits and
92 * in both directions (VPN to exit and exit to VPN).
93 */
94struct GNUNET_EXIT_TcpDataMessage
95{
96 /**
97 * Type is #GNUNET_MESSAGE_TYPE_VPN_TCP_DATA
98 */
99 struct GNUNET_MessageHeader header;
100
101 /**
102 * Always 0.
103 */
104 uint32_t reserved GNUNET_PACKED;
105
106 /**
107 * Skeleton of the TCP header to send. Port numbers are to
108 * be replaced and the checksum may be updated as necessary. (The destination port number should not be changed, as it contains the desired destination port.)
109 */
110 struct GNUNET_TUN_TcpHeader tcp_header;
111
112 /* followed by TCP payload */
113};
114
115
116/**
117 * Message send via cadet to an exit daemon to send
118 * UDP data to a local service.
119 */
120struct GNUNET_EXIT_UdpServiceMessage
121{
122 /**
123 * Type is #GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE
124 */
125 struct GNUNET_MessageHeader header;
126
127 /**
128 * Source port to use for the UDP request (0 to use a random port). In NBO.
129 */
130 uint16_t source_port GNUNET_PACKED;
131
132 /**
133 * Destination port to use for the UDP request. In NBO.
134 */
135 uint16_t destination_port GNUNET_PACKED;
136
137 /* followed by UDP payload */
138};
139
140
141/**
142 * Message send via cadet to an exit daemon to forward
143 * UDP data to the Internet.
144 */
145struct GNUNET_EXIT_UdpInternetMessage
146{
147 /**
148 * Type is #GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET
149 */
150 struct GNUNET_MessageHeader header;
151
152 /**
153 * Address family, AF_INET or AF_INET6, in network byte order.
154 */
155 int32_t af GNUNET_PACKED;
156
157 /**
158 * Source port to use for the UDP request (0 to use a random port). In NBO.
159 */
160 uint16_t source_port GNUNET_PACKED;
161
162 /**
163 * Destination port to use for the UDP request. In NBO.
164 */
165 uint16_t destination_port GNUNET_PACKED;
166
167 /* followed by IP address of the destination; either
168 'struct in_addr' or 'struct in6_addr', depending on af */
169
170 /* followed by UDP payload */
171};
172
173
174/**
175 * Message send from exit daemon back to the UDP entry point
176 * (used for both Internet and Service exit replies).
177 */
178struct GNUNET_EXIT_UdpReplyMessage
179{
180 /**
181 * Type is #GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY
182 */
183 struct GNUNET_MessageHeader header;
184
185 /**
186 * Source port to use for the UDP reply (0 to use the same
187 * port as for the original request). In NBO.
188 */
189 uint16_t source_port GNUNET_PACKED;
190
191 /**
192 * Destination port to use for the UDP reply (0 to use the same
193 * port as for the original request). In NBO.
194 */
195 uint16_t destination_port GNUNET_PACKED;
196
197 /* followed by UDP payload */
198};
199
200
201/**
202 * Message send via cadet to an exit daemon to send
203 * ICMP data to a local service.
204 */
205struct GNUNET_EXIT_IcmpServiceMessage
206{
207 /**
208 * Type is #GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE
209 */
210 struct GNUNET_MessageHeader header;
211
212 /**
213 * Address family, AF_INET or AF_INET6, in network byte order. This
214 * AF value determines if the 'icmp_header' is ICMPv4 or ICMPv6.
215 * The receiver (exit) may still have to translate (PT) to the services'
216 * ICMP version (if possible).
217 */
218 int32_t af GNUNET_PACKED;
219
220 /**
221 * ICMP header to use.
222 */
223 struct GNUNET_TUN_IcmpHeader icmp_header;
224
225 /* followed by ICMP payload; however, for certain ICMP message
226 types where the payload is the original IP packet, the payload
227 is omitted as it is useless for the receiver (who will need
228 to create some fake payload manually) */
229};
230
231
232/**
233 * Message send via cadet to an exit daemon to forward
234 * ICMP data to the Internet.
235 */
236struct GNUNET_EXIT_IcmpInternetMessage
237{
238 /**
239 * Type is #GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET
240 */
241 struct GNUNET_MessageHeader header;
242
243 /**
244 * Address family, AF_INET or AF_INET6, in network byte order.
245 * Determines both the ICMP version used in the 'icmp_header' and
246 * the IP address format that is used for the target IP. If
247 * PT is necessary, the sender has already done it.
248 */
249 int32_t af GNUNET_PACKED;
250
251 /**
252 * ICMP header to use. Must match the target 'af' given
253 * above.
254 */
255 struct GNUNET_TUN_IcmpHeader icmp_header;
256
257 /* followed by IP address of the destination; either
258 'struct in_addr' or 'struct in6_addr', depending on af */
259
260 /* followed by ICMP payload; however, for certain ICMP message
261 types where the payload is the original IP packet, the payload
262 is omitted as it is useless for the receiver (who will need
263 to create some fake payload manually) */
264};
265
266
267/**
268 * Message send via cadet to the vpn service to send
269 * ICMP data to the VPN's TUN interface.
270 */
271struct GNUNET_EXIT_IcmpToVPNMessage
272{
273 /**
274 * Type is #GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN
275 */
276 struct GNUNET_MessageHeader header;
277
278 /**
279 * Address family, AF_INET or AF_INET6, in network byte order.
280 * Useful to determine if this is an ICMPv4 or ICMPv6 header.
281 */
282 int32_t af GNUNET_PACKED;
283
284 /**
285 * ICMP header to use. ICMPv4 or ICMPv6, depending on 'af'.
286 */
287 struct GNUNET_TUN_IcmpHeader icmp_header;
288
289 /* followed by ICMP payload; however, for certain ICMP message
290 types where the payload is the original IP packet, the payload
291 is omitted as it is useless for the receiver (who will need
292 to create some fake payload manually) */
293};
294
295
296GNUNET_NETWORK_STRUCT_END
297
298#endif
diff --git a/src/exit/gnunet-daemon-exit.c b/src/exit/gnunet-daemon-exit.c
deleted file mode 100644
index f4a17e32a..000000000
--- a/src/exit/gnunet-daemon-exit.c
+++ /dev/null
@@ -1,4125 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010-2013, 2017 Christian Grothoff
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file exit/gnunet-daemon-exit.c
23 * @brief tool to allow IP traffic exit from the GNUnet cadet to the Internet
24 * @author Philipp Toelke
25 * @author Christian Grothoff
26 *
27 * TODO:
28 * - test
29 *
30 * Design:
31 * - which code should advertise services? the service model is right
32 * now a bit odd, especially as this code DOES the exit and knows
33 * the DNS "name", but OTOH this is clearly NOT the place to advertise
34 * the service's existence; maybe the daemon should turn into a
35 * service with an API to add local-exit services dynamically?
36 */
37#include "platform.h"
38#include "gnunet_util_lib.h"
39#include "gnunet_protocols.h"
40#include "gnunet_applications.h"
41#include "gnunet_dht_service.h"
42#include "gnunet_cadet_service.h"
43#include "gnunet_dnsparser_lib.h"
44#include "gnunet_dnsstub_lib.h"
45#include "gnunet_statistics_service.h"
46#include "gnunet_constants.h"
47#include "gnunet_signatures.h"
48#include "gnunet_tun_lib.h"
49#include "gnunet_regex_service.h"
50#include "exit.h"
51#include "block_dns.h"
52
53
54/**
55 * Maximum path compression length for cadet regex announcing for IPv4 address
56 * based regex.
57 */
58#define REGEX_MAX_PATH_LEN_IPV4 4
59
60/**
61 * Maximum path compression length for cadet regex announcing for IPv6 address
62 * based regex.
63 */
64#define REGEX_MAX_PATH_LEN_IPV6 8
65
66/**
67 * How frequently do we re-announce the regex for the exit?
68 */
69#define REGEX_REFRESH_FREQUENCY GNUNET_TIME_relative_multiply ( \
70 GNUNET_TIME_UNIT_MINUTES, 30)
71
72/**
73 * How frequently do we re-announce the DNS exit in the DHT?
74 */
75#define DHT_PUT_FREQUENCY GNUNET_TIME_relative_multiply ( \
76 GNUNET_TIME_UNIT_MINUTES, 15)
77
78/**
79 * How long do we typically sign the DNS exit advertisement for?
80 */
81#define DNS_ADVERTISEMENT_TIMEOUT GNUNET_TIME_relative_multiply ( \
82 GNUNET_TIME_UNIT_HOURS, 3)
83
84
85/**
86 * Generic logging shorthand
87 */
88#define LOG(kind, ...) \
89 GNUNET_log_from (kind, "exit", __VA_ARGS__);
90
91
92/**
93 * Information about an address.
94 */
95struct SocketAddress
96{
97 /**
98 * AF_INET or AF_INET6.
99 */
100 int af;
101
102 /**
103 * Remote address information.
104 */
105 union
106 {
107 /**
108 * Address, if af is AF_INET.
109 */
110 struct in_addr ipv4;
111
112 /**
113 * Address, if af is AF_INET6.
114 */
115 struct in6_addr ipv6;
116 } address;
117
118 /**
119 * IPPROTO_TCP or IPPROTO_UDP;
120 */
121 uint8_t proto;
122
123 /**
124 * Remote port, in host byte order!
125 */
126 uint16_t port;
127};
128
129
130/**
131 * This struct is saved into the services-hashmap to represent
132 * a service this peer is specifically offering an exit for
133 * (for a specific domain name).
134 */
135struct LocalService
136{
137 /**
138 * Remote address to use for the service.
139 */
140 struct SocketAddress address;
141
142 /**
143 * Descriptor for the service (CADET port).
144 */
145 struct GNUNET_HashCode descriptor;
146
147 /**
148 * DNS name of the service.
149 */
150 char *name;
151
152 /**
153 * Open port with CADET.
154 */
155 struct GNUNET_CADET_Port *port;
156
157 /**
158 * #GNUNET_YES if this is a UDP service, otherwise TCP.
159 */
160 int16_t is_udp;
161};
162
163
164/**
165 * Information we use to track a connection (the classical 6-tuple of
166 * IP-version, protocol, source-IP, destination-IP, source-port and
167 * destinatin-port.
168 */
169struct RedirectInformation
170{
171 /**
172 * Address information for the other party (equivalent of the
173 * arguments one would give to "connect").
174 */
175 struct SocketAddress remote_address;
176
177 /**
178 * Address information we used locally (AF and proto must match
179 * "remote_address"). Equivalent of the arguments one would give to
180 * "bind".
181 */
182 struct SocketAddress local_address;
183
184 /*
185 Note 1: additional information might be added here in the
186 future to support protocols that require special handling,
187 such as ftp/tftp
188
189 Note 2: we might also sometimes not match on all components
190 of the tuple, to support protocols where things do not always
191 fully map.
192 */
193};
194
195
196/**
197 * This struct is saved into #connections_map to allow finding the
198 * right channel given an IP packet from TUN. It is also associated
199 * with the channel's closure so we can find it again for the next
200 * message from the channel.
201 */
202struct ChannelState
203{
204 /**
205 * Cadet channel that is used for this connection.
206 */
207 struct GNUNET_CADET_Channel *channel;
208
209 /**
210 * Who is the other end of this channel.
211 * FIXME is this needed? Only used for debugging messages
212 */
213 struct GNUNET_PeerIdentity peer;
214
215 /**
216 * #GNUNET_NO if this is a channel for TCP/UDP,
217 * #GNUNET_YES if this is a channel for DNS,
218 * #GNUNET_SYSERR if the channel is not yet initialized.
219 */
220 int is_dns;
221
222 union
223 {
224 struct
225 {
226 /**
227 * Heap node for this state in the connections_heap.
228 */
229 struct GNUNET_CONTAINER_HeapNode *heap_node;
230
231 /**
232 * Key this state has in the #connections_map.
233 */
234 struct GNUNET_HashCode state_key;
235
236 /**
237 * Associated service record, or NULL for no service.
238 */
239 struct LocalService *serv;
240
241 /**
242 * Primary redirection information for this connection.
243 */
244 struct RedirectInformation ri;
245 } tcp_udp;
246
247 struct
248 {
249 /**
250 * Socket we are using to transmit this request (must match if we receive
251 * a response).
252 */
253 struct GNUNET_DNSSTUB_RequestSocket *rs;
254
255 /**
256 * Original DNS request ID as used by the client.
257 */
258 uint16_t original_id;
259
260 /**
261 * DNS request ID that we used for forwarding.
262 */
263 uint16_t my_id;
264 } dns;
265 } specifics;
266};
267
268
269/**
270 * Return value from 'main'.
271 */
272static int global_ret;
273
274/**
275 * Handle to our regex announcement for IPv4.
276 */
277static struct GNUNET_REGEX_Announcement *regex4;
278
279/**
280 * Handle to our regex announcement for IPv4.
281 */
282static struct GNUNET_REGEX_Announcement *regex6;
283
284/**
285 * The handle to the configuration used throughout the process
286 */
287static const struct GNUNET_CONFIGURATION_Handle *cfg;
288
289/**
290 * The handle to the helper
291 */
292static struct GNUNET_HELPER_Handle *helper_handle;
293
294/**
295 * Arguments to the exit helper.
296 */
297static char *exit_argv[8];
298
299/**
300 * IPv6 address of our TUN interface.
301 */
302static struct in6_addr exit_ipv6addr;
303
304/**
305 * IPv6 prefix (0..127) from configuration file.
306 */
307static unsigned long long ipv6prefix;
308
309/**
310 * IPv4 address of our TUN interface.
311 */
312static struct in_addr exit_ipv4addr;
313
314/**
315 * IPv4 netmask of our TUN interface.
316 */
317static struct in_addr exit_ipv4mask;
318
319/**
320 * Statistics.
321 */
322static struct GNUNET_STATISTICS_Handle *stats;
323
324/**
325 * The handle to cadet
326 */
327static struct GNUNET_CADET_Handle *cadet_handle;
328
329/**
330 * This hashmaps contains the mapping from peer, service-descriptor,
331 * source-port and destination-port to a struct ChannelState
332 */
333static struct GNUNET_CONTAINER_MultiHashMap *connections_map;
334
335/**
336 * Heap so we can quickly find "old" connections.
337 */
338static struct GNUNET_CONTAINER_Heap *connections_heap;
339
340/**
341 * If there are at least this many connections, old ones will be removed
342 */
343static unsigned long long max_connections;
344
345/**
346 * This hashmaps saves interesting things about the configured services
347 */
348static struct GNUNET_CONTAINER_MultiHashMap *services;
349
350/**
351 * Array of all open DNS requests from channels.
352 */
353static struct ChannelState *channels[UINT16_MAX + 1];
354
355/**
356 * Handle to the DNS Stub resolver.
357 */
358static struct GNUNET_DNSSTUB_Context *dnsstub;
359
360/**
361 * Handle for ongoing DHT PUT operations to advertise exit service.
362 */
363static struct GNUNET_DHT_PutHandle *dht_put;
364
365/**
366 * Handle to the DHT.
367 */
368static struct GNUNET_DHT_Handle *dht;
369
370/**
371 * Task for doing DHT PUTs to advertise exit service.
372 */
373static struct GNUNET_SCHEDULER_Task *dht_task;
374
375/**
376 * Advertisement message we put into the DHT to advertise us
377 * as a DNS exit.
378 */
379static struct GNUNET_DNS_Advertisement dns_advertisement;
380
381/**
382 * Key we store the DNS advertismenet under.
383 */
384static struct GNUNET_HashCode dht_put_key;
385
386/**
387 * Private key for this peer.
388 */
389static struct GNUNET_CRYPTO_EddsaPrivateKey *peer_key;
390
391/**
392 * Port for DNS exit.
393 */
394static struct GNUNET_CADET_Port *dns_port;
395
396/**
397 * Port for IPv4 exit.
398 */
399static struct GNUNET_CADET_Port *cadet_port4;
400
401/**
402 * Port for IPv6 exit.
403 */
404static struct GNUNET_CADET_Port *cadet_port6;
405
406/**
407 * Are we an IPv4-exit?
408 */
409static int ipv4_exit;
410
411/**
412 * Are we an IPv6-exit?
413 */
414static int ipv6_exit;
415
416/**
417 * Do we support IPv4 at all on the TUN interface?
418 */
419static int ipv4_enabled;
420
421/**
422 * Do we support IPv6 at all on the TUN interface?
423 */
424static int ipv6_enabled;
425
426
427GNUNET_NETWORK_STRUCT_BEGIN
428
429/**
430 * Message with a DNS response.
431 */
432struct DnsResponseMessage
433{
434 /**
435 * GNUnet header, of type #GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET
436 */
437 struct GNUNET_MessageHeader header;
438
439 /**
440 * DNS header.
441 */
442 struct GNUNET_TUN_DnsHeader dns;
443
444 /* Followed by more DNS payload */
445};
446
447GNUNET_NETWORK_STRUCT_END
448
449
450/**
451 * Callback called from DNSSTUB resolver when a resolution
452 * succeeded.
453 *
454 * @param cls NULL
455 * @param dns the response itself
456 * @param r number of bytes in @a dns
457 */
458static void
459process_dns_result (void *cls,
460 const struct GNUNET_TUN_DnsHeader *dns,
461 size_t r)
462{
463 struct ChannelState *ts;
464 struct GNUNET_MQ_Envelope *env;
465 struct DnsResponseMessage *resp;
466
467 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
468 "Processing DNS result from stub resolver\n");
469 GNUNET_assert (NULL == cls);
470 if (NULL == dns)
471 return;
472 /* Handle case that this is a reply to a request from a CADET DNS channel */
473 ts = channels[dns->id];
474 if (NULL == ts)
475 return;
476 LOG (GNUNET_ERROR_TYPE_DEBUG,
477 "Got a response from the stub resolver for DNS request received via CADET!\n");
478 channels[dns->id] = NULL;
479 env = GNUNET_MQ_msg_extra (resp,
480 r - sizeof(struct GNUNET_TUN_DnsHeader),
481 GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET);
482 GNUNET_memcpy (&resp->dns,
483 dns,
484 r);
485 resp->dns.id = ts->specifics.dns.original_id;
486 GNUNET_MQ_send (GNUNET_CADET_get_mq (ts->channel),
487 env);
488}
489
490
491/**
492 * Check a request via cadet to perform a DNS query.
493 *
494 * @param cls our `struct ChannelState *`
495 * @param msg the actual message
496 * @return #GNUNET_OK to keep the connection open,
497 * #GNUNET_SYSERR to close it (signal serious error)
498 */
499static int
500check_dns_request (void *cls,
501 const struct DnsResponseMessage *msg)
502{
503 struct ChannelState *ts = cls;
504
505 if (NULL == dnsstub)
506 {
507 GNUNET_break (0);
508 return GNUNET_SYSERR;
509 }
510 if (GNUNET_NO == ts->is_dns)
511 {
512 GNUNET_break_op (0);
513 return GNUNET_SYSERR;
514 }
515 return GNUNET_OK;
516}
517
518
519/**
520 * Process a request via cadet to perform a DNS query.
521 *
522 * @param cls our `struct ChannelState *`
523 * @param msg the actual message
524 */
525static void
526handle_dns_request (void *cls,
527 const struct DnsResponseMessage *msg)
528{
529 struct ChannelState *ts = cls;
530 size_t mlen = ntohs (msg->header.size);
531 size_t dlen = mlen - sizeof(struct GNUNET_MessageHeader);
532 char buf[dlen] GNUNET_ALIGN;
533 struct GNUNET_TUN_DnsHeader *dns_out;
534
535 if (GNUNET_SYSERR == ts->is_dns)
536 {
537 /* channel is DNS from now on */
538 ts->is_dns = GNUNET_YES;
539 }
540 ts->specifics.dns.original_id = msg->dns.id;
541 if (channels[ts->specifics.dns.my_id] == ts)
542 channels[ts->specifics.dns.my_id] = NULL;
543 ts->specifics.dns.my_id = (uint16_t) GNUNET_CRYPTO_random_u32 (
544 GNUNET_CRYPTO_QUALITY_WEAK,
545 UINT16_MAX
546 + 1);
547 channels[ts->specifics.dns.my_id] = ts;
548 GNUNET_memcpy (buf,
549 &msg->dns,
550 dlen);
551 dns_out = (struct GNUNET_TUN_DnsHeader *) buf;
552 dns_out->id = ts->specifics.dns.my_id;
553 ts->specifics.dns.rs = GNUNET_DNSSTUB_resolve (dnsstub,
554 buf,
555 dlen,
556 &process_dns_result,
557 NULL);
558 if (NULL == ts->specifics.dns.rs)
559 {
560 GNUNET_break_op (0);
561 return;
562 }
563 GNUNET_CADET_receive_done (ts->channel);
564}
565
566
567/**
568 * Given IP information about a connection, calculate the respective
569 * hash we would use for the #connections_map.
570 *
571 * @param hash resulting hash
572 * @param ri information about the connection
573 */
574static void
575hash_redirect_info (struct GNUNET_HashCode *hash,
576 const struct RedirectInformation *ri)
577{
578 char *off;
579
580 memset (hash,
581 0,
582 sizeof(struct GNUNET_HashCode));
583 /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
584 so we put the IP address in there (and hope for few collisions) */
585 off = (char *) hash;
586 switch (ri->remote_address.af)
587 {
588 case AF_INET:
589 GNUNET_memcpy (off,
590 &ri->remote_address.address.ipv4,
591 sizeof(struct in_addr));
592 off += sizeof(struct in_addr);
593 break;
594
595 case AF_INET6:
596 GNUNET_memcpy (off,
597 &ri->remote_address.address.ipv6,
598 sizeof(struct in6_addr));
599 off += sizeof(struct in_addr);
600 break;
601
602 default:
603 GNUNET_assert (0);
604 }
605 GNUNET_memcpy (off,
606 &ri->remote_address.port,
607 sizeof(uint16_t));
608 off += sizeof(uint16_t);
609 switch (ri->local_address.af)
610 {
611 case AF_INET:
612 GNUNET_memcpy (off,
613 &ri->local_address.address.ipv4,
614 sizeof(struct in_addr));
615 off += sizeof(struct in_addr);
616 break;
617
618 case AF_INET6:
619 GNUNET_memcpy (off,
620 &ri->local_address.address.ipv6,
621 sizeof(struct in6_addr));
622 off += sizeof(struct in_addr);
623 break;
624
625 default:
626 GNUNET_assert (0);
627 }
628 GNUNET_memcpy (off,
629 &ri->local_address.port,
630 sizeof(uint16_t));
631 off += sizeof(uint16_t);
632 GNUNET_memcpy (off,
633 &ri->remote_address.proto,
634 sizeof(uint8_t));
635 /* off += sizeof (uint8_t); */
636}
637
638
639/**
640 * Get our connection tracking state. Warns if it does not exists,
641 * refreshes the timestamp if it does exist.
642 *
643 * @param af address family
644 * @param protocol IPPROTO_UDP or IPPROTO_TCP
645 * @param destination_ip target IP
646 * @param destination_port target port
647 * @param local_ip local IP
648 * @param local_port local port
649 * @param state_key set to hash's state if non-NULL
650 * @return NULL if we have no tracking information for this tuple
651 */
652static struct ChannelState *
653get_redirect_state (int af,
654 int protocol,
655 const void *destination_ip,
656 uint16_t destination_port,
657 const void *local_ip,
658 uint16_t local_port,
659 struct GNUNET_HashCode *state_key)
660{
661 struct RedirectInformation ri;
662 struct GNUNET_HashCode key;
663 struct ChannelState *state;
664
665 if (((af == AF_INET) && (protocol == IPPROTO_ICMP)) ||
666 ((af == AF_INET6) && (protocol == IPPROTO_ICMPV6)))
667 {
668 /* ignore ports */
669 destination_port = 0;
670 local_port = 0;
671 }
672 ri.remote_address.af = af;
673 if (af == AF_INET)
674 ri.remote_address.address.ipv4 = *((struct in_addr*) destination_ip);
675 else
676 ri.remote_address.address.ipv6 = *((struct in6_addr*) destination_ip);
677 ri.remote_address.port = destination_port;
678 ri.remote_address.proto = protocol;
679 ri.local_address.af = af;
680 if (af == AF_INET)
681 ri.local_address.address.ipv4 = *((struct in_addr*) local_ip);
682 else
683 ri.local_address.address.ipv6 = *((struct in6_addr*) local_ip);
684 ri.local_address.port = local_port;
685 ri.local_address.proto = protocol;
686 hash_redirect_info (&key,
687 &ri);
688 if (NULL != state_key)
689 *state_key = key;
690 state = GNUNET_CONTAINER_multihashmap_get (connections_map,
691 &key);
692 if (NULL == state)
693 return NULL;
694 /* Mark this connection as freshly used */
695 if (NULL == state_key)
696 GNUNET_CONTAINER_heap_update_cost (state->specifics.tcp_udp.heap_node,
697 GNUNET_TIME_absolute_get ().abs_value_us);
698 return state;
699}
700
701
702/**
703 * Check a request via cadet to send a request to a TCP service
704 * offered by this system.
705 *
706 * @param cls our `struct ChannelState *`
707 * @param start the actual message
708 * @return #GNUNET_OK to keep the connection open,
709 * #GNUNET_SYSERR to close it (signal serious error)
710 */
711static int
712check_tcp_service (void *cls,
713 const struct GNUNET_EXIT_TcpServiceStartMessage *start)
714{
715 struct ChannelState *state = cls;
716
717 if (NULL == state)
718 {
719 GNUNET_break_op (0);
720 return GNUNET_SYSERR;
721 }
722 if (GNUNET_YES == state->is_dns)
723 {
724 GNUNET_break_op (0);
725 return GNUNET_SYSERR;
726 }
727 if (NULL == state->specifics.tcp_udp.serv)
728 {
729 GNUNET_break_op (0);
730 return GNUNET_SYSERR;
731 }
732 if (NULL != state->specifics.tcp_udp.heap_node)
733 {
734 GNUNET_break_op (0);
735 return GNUNET_SYSERR;
736 }
737 if (start->tcp_header.off * 4 < sizeof(struct GNUNET_TUN_TcpHeader))
738 {
739 GNUNET_break_op (0);
740 return GNUNET_SYSERR;
741 }
742 return GNUNET_OK;
743}
744
745
746/**
747 * Prepare an IPv4 packet for transmission via the TUN interface.
748 * Initializes the IP header and calculates checksums (IP+UDP/TCP).
749 * For UDP, the UDP header will be fully created, whereas for TCP
750 * only the ports and checksum will be filled in. So for TCP,
751 * a skeleton TCP header must be part of the provided payload.
752 *
753 * @param payload payload of the packet (starting with UDP payload or
754 * TCP header, depending on protocol)
755 * @param payload_length number of bytes in @a payload
756 * @param protocol IPPROTO_UDP or IPPROTO_TCP
757 * @param tcp_header skeleton of the TCP header, NULL for UDP
758 * @param src_address source address to use (IP and port)
759 * @param dst_address destination address to use (IP and port)
760 * @param pkt4 where to write the assembled packet; must
761 * contain enough space for the IP header, UDP/TCP header
762 * AND the payload
763 */
764static void
765prepare_ipv4_packet (const void *payload,
766 size_t payload_length,
767 int protocol,
768 const struct GNUNET_TUN_TcpHeader *tcp_header,
769 const struct SocketAddress *src_address,
770 const struct SocketAddress *dst_address,
771 struct GNUNET_TUN_IPv4Header *pkt4)
772{
773 size_t len;
774
775 len = payload_length;
776 switch (protocol)
777 {
778 case IPPROTO_UDP:
779 len += sizeof(struct GNUNET_TUN_UdpHeader);
780 break;
781
782 case IPPROTO_TCP:
783 len += sizeof(struct GNUNET_TUN_TcpHeader);
784 GNUNET_assert (NULL != tcp_header);
785 break;
786
787 default:
788 GNUNET_break (0);
789 return;
790 }
791 if (len + sizeof(struct GNUNET_TUN_IPv4Header) > UINT16_MAX)
792 {
793 GNUNET_break (0);
794 return;
795 }
796
797 GNUNET_TUN_initialize_ipv4_header (pkt4,
798 protocol,
799 len,
800 &src_address->address.ipv4,
801 &dst_address->address.ipv4);
802 switch (protocol)
803 {
804 case IPPROTO_UDP:
805 {
806 struct GNUNET_TUN_UdpHeader *pkt4_udp = (struct
807 GNUNET_TUN_UdpHeader *) &pkt4[1];
808
809 pkt4_udp->source_port = htons (src_address->port);
810 pkt4_udp->destination_port = htons (dst_address->port);
811 pkt4_udp->len = htons ((uint16_t) payload_length);
812 GNUNET_TUN_calculate_udp4_checksum (pkt4,
813 pkt4_udp,
814 payload,
815 payload_length);
816 GNUNET_memcpy (&pkt4_udp[1],
817 payload,
818 payload_length);
819 }
820 break;
821
822 case IPPROTO_TCP:
823 {
824 struct GNUNET_TUN_TcpHeader *pkt4_tcp = (struct
825 GNUNET_TUN_TcpHeader *) &pkt4[1];
826
827 *pkt4_tcp = *tcp_header;
828 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
829 "Sending TCP packet from port %u to port %u\n",
830 src_address->port,
831 dst_address->port);
832 pkt4_tcp->source_port = htons (src_address->port);
833 pkt4_tcp->destination_port = htons (dst_address->port);
834 GNUNET_TUN_calculate_tcp4_checksum (pkt4,
835 pkt4_tcp,
836 payload,
837 payload_length);
838 GNUNET_memcpy (&pkt4_tcp[1],
839 payload,
840 payload_length);
841 }
842 break;
843
844 default:
845 GNUNET_assert (0);
846 }
847}
848
849
850/**
851 * Prepare an IPv6 packet for transmission via the TUN interface.
852 * Initializes the IP header and calculates checksums (IP+UDP/TCP).
853 * For UDP, the UDP header will be fully created, whereas for TCP
854 * only the ports and checksum will be filled in. So for TCP,
855 * a skeleton TCP header must be part of the provided payload.
856 *
857 * @param payload payload of the packet (starting with UDP payload or
858 * TCP header, depending on protocol)
859 * @param payload_length number of bytes in @a payload
860 * @param protocol IPPROTO_UDP or IPPROTO_TCP
861 * @param tcp_header skeleton TCP header data to send, NULL for UDP
862 * @param src_address source address to use (IP and port)
863 * @param dst_address destination address to use (IP and port)
864 * @param pkt6 where to write the assembled packet; must
865 * contain enough space for the IP header, UDP/TCP header
866 * AND the payload
867 */
868static void
869prepare_ipv6_packet (const void *payload,
870 size_t payload_length,
871 int protocol,
872 const struct GNUNET_TUN_TcpHeader *tcp_header,
873 const struct SocketAddress *src_address,
874 const struct SocketAddress *dst_address,
875 struct GNUNET_TUN_IPv6Header *pkt6)
876{
877 size_t len;
878
879 len = payload_length;
880 switch (protocol)
881 {
882 case IPPROTO_UDP:
883 len += sizeof(struct GNUNET_TUN_UdpHeader);
884 break;
885
886 case IPPROTO_TCP:
887 len += sizeof(struct GNUNET_TUN_TcpHeader);
888 break;
889
890 default:
891 GNUNET_break (0);
892 return;
893 }
894 if (len > UINT16_MAX)
895 {
896 GNUNET_break (0);
897 return;
898 }
899
900 GNUNET_TUN_initialize_ipv6_header (pkt6,
901 protocol,
902 len,
903 &src_address->address.ipv6,
904 &dst_address->address.ipv6);
905
906 switch (protocol)
907 {
908 case IPPROTO_UDP:
909 {
910 struct GNUNET_TUN_UdpHeader *pkt6_udp = (struct
911 GNUNET_TUN_UdpHeader *) &pkt6[1];
912
913 pkt6_udp->source_port = htons (src_address->port);
914 pkt6_udp->destination_port = htons (dst_address->port);
915 pkt6_udp->len = htons ((uint16_t) payload_length);
916 GNUNET_TUN_calculate_udp6_checksum (pkt6,
917 pkt6_udp,
918 payload,
919 payload_length);
920 GNUNET_memcpy (&pkt6_udp[1],
921 payload,
922 payload_length);
923 }
924 break;
925
926 case IPPROTO_TCP:
927 {
928 struct GNUNET_TUN_TcpHeader *pkt6_tcp = (struct
929 GNUNET_TUN_TcpHeader *) &pkt6[1];
930
931 /* GNUNET_memcpy first here as some TCP header fields are initialized this way! */
932 *pkt6_tcp = *tcp_header;
933 pkt6_tcp->source_port = htons (src_address->port);
934 pkt6_tcp->destination_port = htons (dst_address->port);
935 GNUNET_TUN_calculate_tcp6_checksum (pkt6,
936 pkt6_tcp,
937 payload,
938 payload_length);
939 GNUNET_memcpy (&pkt6_tcp[1],
940 payload,
941 payload_length);
942 }
943 break;
944
945 default:
946 GNUNET_assert (0);
947 break;
948 }
949}
950
951
952/**
953 * Send a TCP packet via the TUN interface.
954 *
955 * @param destination_address IP and port to use for the TCP packet's destination
956 * @param source_address IP and port to use for the TCP packet's source
957 * @param tcp_header header template to use
958 * @param payload payload of the TCP packet
959 * @param payload_length number of bytes in @a payload
960 */
961static void
962send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
963 const struct SocketAddress *source_address,
964 const struct GNUNET_TUN_TcpHeader *tcp_header,
965 const void *payload,
966 size_t payload_length)
967{
968 size_t len;
969
970 GNUNET_STATISTICS_update (stats,
971 gettext_noop ("# TCP packets sent via TUN"),
972 1,
973 GNUNET_NO);
974 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
975 "Sending packet with %u bytes TCP payload via TUN\n",
976 (unsigned int) payload_length);
977 len = sizeof(struct GNUNET_MessageHeader) + sizeof(struct
978 GNUNET_TUN_Layer2PacketHeader);
979 switch (source_address->af)
980 {
981 case AF_INET:
982 len += sizeof(struct GNUNET_TUN_IPv4Header);
983 break;
984
985 case AF_INET6:
986 len += sizeof(struct GNUNET_TUN_IPv6Header);
987 break;
988
989 default:
990 GNUNET_break (0);
991 return;
992 }
993 len += sizeof(struct GNUNET_TUN_TcpHeader);
994 len += payload_length;
995 if (len >= GNUNET_MAX_MESSAGE_SIZE)
996 {
997 GNUNET_break (0);
998 return;
999 }
1000 {
1001 char buf[len] GNUNET_ALIGN;
1002 struct GNUNET_MessageHeader *hdr;
1003 struct GNUNET_TUN_Layer2PacketHeader *tun;
1004
1005 hdr = (struct GNUNET_MessageHeader *) buf;
1006 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1007 hdr->size = htons (len);
1008 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1009 tun->flags = htons (0);
1010 switch (source_address->af)
1011 {
1012 case AF_INET:
1013 {
1014 struct GNUNET_TUN_IPv4Header *ipv4
1015 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
1016
1017 tun->proto = htons (ETH_P_IPV4);
1018 prepare_ipv4_packet (payload,
1019 payload_length,
1020 IPPROTO_TCP,
1021 tcp_header,
1022 source_address,
1023 destination_address,
1024 ipv4);
1025 }
1026 break;
1027
1028 case AF_INET6:
1029 {
1030 struct GNUNET_TUN_IPv6Header *ipv6
1031 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1032
1033 tun->proto = htons (ETH_P_IPV6);
1034 prepare_ipv6_packet (payload,
1035 payload_length,
1036 IPPROTO_TCP,
1037 tcp_header,
1038 source_address,
1039 destination_address,
1040 ipv6);
1041 }
1042 break;
1043
1044 default:
1045 GNUNET_assert (0);
1046 break;
1047 }
1048 if (NULL != helper_handle)
1049 (void) GNUNET_HELPER_send (helper_handle,
1050 (const struct GNUNET_MessageHeader*) buf,
1051 GNUNET_YES,
1052 NULL,
1053 NULL);
1054 }
1055}
1056
1057
1058/**
1059 * Send an ICMP packet via the TUN interface.
1060 *
1061 * @param destination_address IP to use for the ICMP packet's destination
1062 * @param source_address IP to use for the ICMP packet's source
1063 * @param icmp_header ICMP header to send
1064 * @param payload payload of the ICMP packet (does NOT include ICMP header)
1065 * @param payload_length number of bytes of data in @a payload
1066 */
1067static void
1068send_icmp_packet_via_tun (const struct SocketAddress *destination_address,
1069 const struct SocketAddress *source_address,
1070 const struct GNUNET_TUN_IcmpHeader *icmp_header,
1071 const void *payload, size_t payload_length)
1072{
1073 size_t len;
1074 struct GNUNET_TUN_IcmpHeader *icmp;
1075
1076 GNUNET_STATISTICS_update (stats,
1077 gettext_noop ("# ICMP packets sent via TUN"),
1078 1, GNUNET_NO);
1079 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1080 "Sending packet with %u bytes ICMP payload via TUN\n",
1081 (unsigned int) payload_length);
1082 len = sizeof(struct GNUNET_MessageHeader) + sizeof(struct
1083 GNUNET_TUN_Layer2PacketHeader);
1084 switch (destination_address->af)
1085 {
1086 case AF_INET:
1087 len += sizeof(struct GNUNET_TUN_IPv4Header);
1088 break;
1089
1090 case AF_INET6:
1091 len += sizeof(struct GNUNET_TUN_IPv6Header);
1092 break;
1093
1094 default:
1095 GNUNET_break (0);
1096 return;
1097 }
1098 len += sizeof(struct GNUNET_TUN_IcmpHeader);
1099 len += payload_length;
1100 if (len >= GNUNET_MAX_MESSAGE_SIZE)
1101 {
1102 GNUNET_break (0);
1103 return;
1104 }
1105 {
1106 char buf[len] GNUNET_ALIGN;
1107 struct GNUNET_MessageHeader *hdr;
1108 struct GNUNET_TUN_Layer2PacketHeader *tun;
1109
1110 hdr = (struct GNUNET_MessageHeader *) buf;
1111 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1112 hdr->size = htons (len);
1113 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1114 tun->flags = htons (0);
1115 switch (source_address->af)
1116 {
1117 case AF_INET:
1118 {
1119 struct GNUNET_TUN_IPv4Header *ipv4 = (struct
1120 GNUNET_TUN_IPv4Header*) &tun[1];
1121
1122 tun->proto = htons (ETH_P_IPV4);
1123 GNUNET_TUN_initialize_ipv4_header (ipv4,
1124 IPPROTO_ICMP,
1125 sizeof(struct
1126 GNUNET_TUN_IcmpHeader)
1127 + payload_length,
1128 &source_address->address.ipv4,
1129 &destination_address->address.ipv4);
1130 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv4[1];
1131 }
1132 break;
1133
1134 case AF_INET6:
1135 {
1136 struct GNUNET_TUN_IPv6Header *ipv6 = (struct
1137 GNUNET_TUN_IPv6Header*) &tun[1];
1138
1139 tun->proto = htons (ETH_P_IPV6);
1140 GNUNET_TUN_initialize_ipv6_header (ipv6,
1141 IPPROTO_ICMPV6,
1142 sizeof(struct
1143 GNUNET_TUN_IcmpHeader)
1144 + payload_length,
1145 &source_address->address.ipv6,
1146 &destination_address->address.ipv6);
1147 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv6[1];
1148 }
1149 break;
1150
1151 default:
1152 GNUNET_assert (0);
1153 break;
1154 }
1155 *icmp = *icmp_header;
1156 GNUNET_memcpy (&icmp[1],
1157 payload,
1158 payload_length);
1159 GNUNET_TUN_calculate_icmp_checksum (icmp,
1160 payload,
1161 payload_length);
1162 if (NULL != helper_handle)
1163 (void) GNUNET_HELPER_send (helper_handle,
1164 (const struct GNUNET_MessageHeader*) buf,
1165 GNUNET_YES,
1166 NULL, NULL);
1167 }
1168}
1169
1170
1171/**
1172 * We need to create a (unique) fresh local address (IP+port).
1173 * Fill one in.
1174 *
1175 * @param af desired address family
1176 * @param proto desired protocol (IPPROTO_UDP or IPPROTO_TCP)
1177 * @param local_address address to initialize
1178 */
1179static void
1180setup_fresh_address (int af,
1181 uint8_t proto,
1182 struct SocketAddress *local_address)
1183{
1184 local_address->af = af;
1185 local_address->proto = (uint8_t) proto;
1186 /* default "local" port range is often 32768--61000,
1187 so we pick a random value in that range */
1188 if (((af == AF_INET) && (proto == IPPROTO_ICMP)) ||
1189 ((af == AF_INET6) && (proto == IPPROTO_ICMPV6)))
1190 local_address->port = 0;
1191 else
1192 local_address->port
1193 = (uint16_t) 32768 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1194 28232);
1195 switch (af)
1196 {
1197 case AF_INET:
1198 {
1199 struct in_addr addr;
1200 struct in_addr mask;
1201 struct in_addr rnd;
1202
1203 addr = exit_ipv4addr;
1204 mask = exit_ipv4mask;
1205 if (0 == ~mask.s_addr)
1206 {
1207 /* only one valid IP anyway */
1208 local_address->address.ipv4 = addr;
1209 return;
1210 }
1211 /* Given 192.168.0.1/255.255.0.0, we want a mask
1212 of '192.168.255.255', thus: */
1213 mask.s_addr = addr.s_addr | ~mask.s_addr;
1214 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
1215 do
1216 {
1217 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1218 UINT32_MAX);
1219 local_address->address.ipv4.s_addr = (addr.s_addr | rnd.s_addr)
1220 & mask.s_addr;
1221 }
1222 while ((local_address->address.ipv4.s_addr == addr.s_addr) ||
1223 (local_address->address.ipv4.s_addr == mask.s_addr));
1224 }
1225 break;
1226
1227 case AF_INET6:
1228 {
1229 struct in6_addr addr;
1230 struct in6_addr mask;
1231 struct in6_addr rnd;
1232 int i;
1233
1234 addr = exit_ipv6addr;
1235 GNUNET_assert (ipv6prefix < 128);
1236 if (ipv6prefix == 127)
1237 {
1238 /* only one valid IP anyway */
1239 local_address->address.ipv6 = addr;
1240 return;
1241 }
1242 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
1243 thus: */
1244 mask = addr;
1245 for (i = 127; i >= ipv6prefix; i--)
1246 mask.s6_addr[i / 8] |= (1 << (i % 8));
1247
1248 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
1249 do
1250 {
1251 for (i = 0; i < 16; i++)
1252 {
1253 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (
1254 GNUNET_CRYPTO_QUALITY_WEAK,
1255 256);
1256 local_address->address.ipv6.s6_addr[i]
1257 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
1258 }
1259 }
1260 while ((0 == GNUNET_memcmp (&local_address->address.ipv6,
1261 &addr)) ||
1262 (0 == GNUNET_memcmp (&local_address->address.ipv6,
1263 &mask)));
1264 }
1265 break;
1266
1267 default:
1268 GNUNET_assert (0);
1269 }
1270}
1271
1272
1273/**
1274 * We are starting a fresh connection (TCP or UDP) and need
1275 * to pick a source port and IP address (within the correct
1276 * range and address family) to associate replies with the
1277 * connection / correct cadet channel. This function generates
1278 * a "fresh" source IP and source port number for a connection
1279 * After picking a good source address, this function sets up
1280 * the state in the 'connections_map' and 'connections_heap'
1281 * to allow finding the state when needed later. The function
1282 * also makes sure that we remain within memory limits by
1283 * cleaning up 'old' states.
1284 *
1285 * @param state skeleton state to setup a record for; should
1286 * 'state->specifics.tcp_udp.ri.remote_address' filled in so that
1287 * this code can determine which AF/protocol is
1288 * going to be used (the 'channel' should also
1289 * already be set); after calling this function,
1290 * heap_node and the local_address will be
1291 * also initialized (heap_node != NULL can be
1292 * used to test if a state has been fully setup).
1293 */
1294static void
1295setup_state_record (struct ChannelState *state)
1296{
1297 struct GNUNET_HashCode key;
1298 struct ChannelState *s;
1299
1300 /* generate fresh, unique address */
1301 do
1302 {
1303 if (NULL == state->specifics.tcp_udp.serv)
1304 setup_fresh_address (state->specifics.tcp_udp.ri.remote_address.af,
1305 state->specifics.tcp_udp.ri.remote_address.proto,
1306 &state->specifics.tcp_udp.ri.local_address);
1307 else
1308 setup_fresh_address (state->specifics.tcp_udp.serv->address.af,
1309 state->specifics.tcp_udp.serv->address.proto,
1310 &state->specifics.tcp_udp.ri.local_address);
1311 }
1312 while (NULL !=
1313 get_redirect_state (state->specifics.tcp_udp.ri.remote_address.af,
1314 state->specifics.tcp_udp.ri.remote_address.proto,
1315 &state->specifics.tcp_udp.ri.remote_address.address,
1316 state->specifics.tcp_udp.ri.remote_address.port,
1317 &state->specifics.tcp_udp.ri.local_address.address,
1318 state->specifics.tcp_udp.ri.local_address.port,
1319 &key));
1320 {
1321 char buf[INET6_ADDRSTRLEN];
1322 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1323 "Picked local address %s:%u for new connection\n",
1324 inet_ntop (state->specifics.tcp_udp.ri.local_address.af,
1325 &state->specifics.tcp_udp.ri.local_address.address,
1326 buf,
1327 sizeof(buf)),
1328 (unsigned int) state->specifics.tcp_udp.ri.local_address.port);
1329 }
1330 state->specifics.tcp_udp.state_key = key;
1331 GNUNET_assert (GNUNET_OK ==
1332 GNUNET_CONTAINER_multihashmap_put (connections_map,
1333 &key, state,
1334 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1335 state->specifics.tcp_udp.heap_node
1336 = GNUNET_CONTAINER_heap_insert (connections_heap,
1337 state,
1338 GNUNET_TIME_absolute_get ().abs_value_us);
1339 while (GNUNET_CONTAINER_heap_get_size (connections_heap) > max_connections)
1340 {
1341 s = GNUNET_CONTAINER_heap_remove_root (connections_heap);
1342 GNUNET_assert (state != s);
1343 s->specifics.tcp_udp.heap_node = NULL;
1344 GNUNET_CADET_channel_destroy (s->channel);
1345 GNUNET_assert (GNUNET_OK ==
1346 GNUNET_CONTAINER_multihashmap_remove (connections_map,
1347 &s->specifics.tcp_udp.
1348 state_key,
1349 s));
1350 GNUNET_free (s);
1351 }
1352}
1353
1354
1355/**
1356 * Send a UDP packet via the TUN interface.
1357 *
1358 * @param destination_address IP and port to use for the UDP packet's destination
1359 * @param source_address IP and port to use for the UDP packet's source
1360 * @param payload payload of the UDP packet (does NOT include UDP header)
1361 * @param payload_length number of bytes of data in @a payload
1362 */
1363static void
1364send_udp_packet_via_tun (const struct SocketAddress *destination_address,
1365 const struct SocketAddress *source_address,
1366 const void *payload, size_t payload_length)
1367{
1368 size_t len;
1369
1370 GNUNET_STATISTICS_update (stats,
1371 gettext_noop ("# UDP packets sent via TUN"),
1372 1, GNUNET_NO);
1373 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1374 "Sending packet with %u bytes UDP payload via TUN\n",
1375 (unsigned int) payload_length);
1376 len = sizeof(struct GNUNET_MessageHeader) + sizeof(struct
1377 GNUNET_TUN_Layer2PacketHeader);
1378 switch (source_address->af)
1379 {
1380 case AF_INET:
1381 len += sizeof(struct GNUNET_TUN_IPv4Header);
1382 break;
1383
1384 case AF_INET6:
1385 len += sizeof(struct GNUNET_TUN_IPv6Header);
1386 break;
1387
1388 default:
1389 GNUNET_break (0);
1390 return;
1391 }
1392 len += sizeof(struct GNUNET_TUN_UdpHeader);
1393 len += payload_length;
1394 if (len >= GNUNET_MAX_MESSAGE_SIZE)
1395 {
1396 GNUNET_break (0);
1397 return;
1398 }
1399 {
1400 char buf[len] GNUNET_ALIGN;
1401 struct GNUNET_MessageHeader *hdr;
1402 struct GNUNET_TUN_Layer2PacketHeader *tun;
1403
1404 hdr = (struct GNUNET_MessageHeader *) buf;
1405 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1406 hdr->size = htons (len);
1407 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1408 tun->flags = htons (0);
1409 switch (source_address->af)
1410 {
1411 case AF_INET:
1412 {
1413 struct GNUNET_TUN_IPv4Header *ipv4 = (struct
1414 GNUNET_TUN_IPv4Header*) &tun[1];
1415
1416 tun->proto = htons (ETH_P_IPV4);
1417 prepare_ipv4_packet (payload,
1418 payload_length,
1419 IPPROTO_UDP,
1420 NULL,
1421 source_address,
1422 destination_address,
1423 ipv4);
1424 }
1425 break;
1426
1427 case AF_INET6:
1428 {
1429 struct GNUNET_TUN_IPv6Header *ipv6 = (struct
1430 GNUNET_TUN_IPv6Header*) &tun[1];
1431
1432 tun->proto = htons (ETH_P_IPV6);
1433 prepare_ipv6_packet (payload,
1434 payload_length,
1435 IPPROTO_UDP,
1436 NULL,
1437 source_address,
1438 destination_address,
1439 ipv6);
1440 }
1441 break;
1442
1443 default:
1444 GNUNET_assert (0);
1445 break;
1446 }
1447 if (NULL != helper_handle)
1448 (void) GNUNET_HELPER_send (helper_handle,
1449 (const struct GNUNET_MessageHeader*) buf,
1450 GNUNET_YES,
1451 NULL, NULL);
1452 }
1453}
1454
1455
1456/**
1457 * Check a request to forward UDP data to the Internet via this peer.
1458 *
1459 * @param cls our `struct ChannelState *`
1460 * @param msg the actual message
1461 * @return #GNUNET_OK to keep the connection open,
1462 * #GNUNET_SYSERR to close it (signal serious error)
1463 */
1464static int
1465check_udp_remote (void *cls,
1466 const struct GNUNET_EXIT_UdpInternetMessage *msg)
1467{
1468 struct ChannelState *state = cls;
1469
1470 if (GNUNET_YES == state->is_dns)
1471 {
1472 GNUNET_break_op (0);
1473 return GNUNET_SYSERR;
1474 }
1475 return GNUNET_OK;
1476}
1477
1478
1479/**
1480 * Process a request to forward UDP data to the Internet via this peer.
1481 *
1482 * @param cls our `struct ChannelState *`
1483 * @param msg the actual message
1484 */
1485static void
1486handle_udp_remote (void *cls,
1487 const struct GNUNET_EXIT_UdpInternetMessage *msg)
1488{
1489 struct ChannelState *state = cls;
1490 uint16_t pkt_len = ntohs (msg->header.size) - sizeof(struct
1491 GNUNET_EXIT_UdpInternetMessage);
1492 const struct in_addr *v4;
1493 const struct in6_addr *v6;
1494 const void *payload;
1495 int af;
1496
1497 if (GNUNET_SYSERR == state->is_dns)
1498 {
1499 /* channel is UDP/TCP from now on */
1500 state->is_dns = GNUNET_NO;
1501 }
1502 GNUNET_STATISTICS_update (stats,
1503 gettext_noop ("# Bytes received from CADET"),
1504 pkt_len, GNUNET_NO);
1505 GNUNET_STATISTICS_update (stats,
1506 gettext_noop (
1507 "# UDP IP-exit requests received via cadet"),
1508 1, GNUNET_NO);
1509 af = (int) ntohl (msg->af);
1510 state->specifics.tcp_udp.ri.remote_address.af = af;
1511 switch (af)
1512 {
1513 case AF_INET:
1514 if (pkt_len < sizeof(struct in_addr))
1515 {
1516 GNUNET_break_op (0);
1517 return;
1518 }
1519 if (! ipv4_exit)
1520 {
1521 GNUNET_break_op (0);
1522 return;
1523 }
1524 v4 = (const struct in_addr*) &msg[1];
1525 payload = &v4[1];
1526 pkt_len -= sizeof(struct in_addr);
1527 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
1528 break;
1529
1530 case AF_INET6:
1531 if (pkt_len < sizeof(struct in6_addr))
1532 {
1533 GNUNET_break_op (0);
1534 return;
1535 }
1536 if (! ipv6_exit)
1537 {
1538 GNUNET_break_op (0);
1539 return;
1540 }
1541 v6 = (const struct in6_addr*) &msg[1];
1542 payload = &v6[1];
1543 pkt_len -= sizeof(struct in6_addr);
1544 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
1545 break;
1546
1547 default:
1548 GNUNET_break_op (0);
1549 return;
1550 }
1551 {
1552 char buf[INET6_ADDRSTRLEN];
1553 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1554 "Received data from %s for forwarding to UDP %s:%u\n",
1555 GNUNET_i2s (&state->peer),
1556 inet_ntop (af,
1557 &state->specifics.tcp_udp.ri.remote_address.address,
1558 buf, sizeof(buf)),
1559 (unsigned int) ntohs (msg->destination_port));
1560 }
1561 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_UDP;
1562 state->specifics.tcp_udp.ri.remote_address.port = msg->destination_port;
1563 if (NULL == state->specifics.tcp_udp.heap_node)
1564 setup_state_record (state);
1565 if (0 != ntohs (msg->source_port))
1566 state->specifics.tcp_udp.ri.local_address.port = msg->source_port;
1567 send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1568 &state->specifics.tcp_udp.ri.local_address,
1569 payload,
1570 pkt_len);
1571 GNUNET_CADET_receive_done (state->channel);
1572}
1573
1574
1575/**
1576 * Check a request via cadet to send a request to a UDP service
1577 * offered by this system.
1578 *
1579 * @param cls our `struct ChannelState *`
1580 * @param msg the actual message
1581 * @return #GNUNET_OK to keep the connection open,
1582 * #GNUNET_SYSERR to close it (signal serious error)
1583 */
1584static int
1585check_udp_service (void *cls,
1586 const struct GNUNET_EXIT_UdpServiceMessage *msg)
1587{
1588 struct ChannelState *state = cls;
1589
1590 if (NULL == state->specifics.tcp_udp.serv)
1591 {
1592 GNUNET_break_op (0);
1593 return GNUNET_SYSERR;
1594 }
1595 return GNUNET_OK;
1596}
1597
1598
1599/**
1600 * Process a request via cadet to send a request to a UDP service
1601 * offered by this system.
1602 *
1603 * @param cls our `struct ChannelState *`
1604 * @param msg the actual message
1605 */
1606static void
1607handle_udp_service (void *cls,
1608 const struct GNUNET_EXIT_UdpServiceMessage *msg)
1609{
1610 struct ChannelState *state = cls;
1611 uint16_t pkt_len = ntohs (msg->header.size) - sizeof(struct
1612 GNUNET_EXIT_UdpServiceMessage);
1613
1614 GNUNET_STATISTICS_update (stats,
1615 gettext_noop ("# Bytes received from CADET"),
1616 pkt_len, GNUNET_NO);
1617 GNUNET_STATISTICS_update (stats,
1618 gettext_noop (
1619 "# UDP service requests received via cadet"),
1620 1, GNUNET_NO);
1621 LOG (GNUNET_ERROR_TYPE_DEBUG,
1622 "Received data from %s for forwarding to UDP service %s on port %u\n",
1623 GNUNET_i2s (&state->peer),
1624 GNUNET_h2s (&state->specifics.tcp_udp.serv->descriptor),
1625 (unsigned int) ntohs (msg->destination_port));
1626 setup_state_record (state);
1627 if (0 != ntohs (msg->source_port))
1628 state->specifics.tcp_udp.ri.local_address.port = msg->source_port;
1629 send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1630 &state->specifics.tcp_udp.ri.local_address,
1631 &msg[1],
1632 pkt_len);
1633 GNUNET_CADET_receive_done (state->channel);
1634}
1635
1636
1637/**
1638 * Process a request via cadet to send a request to a TCP service
1639 * offered by this system.
1640 *
1641 * @param cls our `struct ChannelState *`
1642 * @param start the actual message
1643 * @return #GNUNET_OK to keep the connection open,
1644 * #GNUNET_SYSERR to close it (signal serious error)
1645 */
1646static void
1647handle_tcp_service (void *cls,
1648 const struct GNUNET_EXIT_TcpServiceStartMessage *start)
1649{
1650 struct ChannelState *state = cls;
1651 uint16_t pkt_len = ntohs (start->header.size) - sizeof(struct
1652 GNUNET_EXIT_TcpServiceStartMessage);
1653
1654 if (GNUNET_SYSERR == state->is_dns)
1655 {
1656 /* channel is UDP/TCP from now on */
1657 state->is_dns = GNUNET_NO;
1658 }
1659 GNUNET_STATISTICS_update (stats,
1660 gettext_noop (
1661 "# TCP service creation requests received via cadet"),
1662 1,
1663 GNUNET_NO);
1664 GNUNET_STATISTICS_update (stats,
1665 gettext_noop ("# Bytes received from CADET"),
1666 pkt_len,
1667 GNUNET_NO);
1668 GNUNET_break_op (ntohl (start->reserved) == 0);
1669 /* setup fresh connection */
1670 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1671 "Received data from %s for forwarding to TCP service %s on port %u\n",
1672 GNUNET_i2s (&state->peer),
1673 GNUNET_h2s (&state->specifics.tcp_udp.serv->descriptor),
1674 (unsigned int) ntohs (start->tcp_header.destination_port));
1675 setup_state_record (state);
1676 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1677 &state->specifics.tcp_udp.ri.local_address,
1678 &start->tcp_header,
1679 &start[1],
1680 pkt_len);
1681 GNUNET_CADET_receive_done (state->channel);
1682}
1683
1684
1685/**
1686 * Check a request to forward TCP data to the Internet via this peer.
1687 *
1688 * @param cls our `struct ChannelState *`
1689 * @param start the actual message
1690 * @return #GNUNET_OK to keep the connection open,
1691 * #GNUNET_SYSERR to close it (signal serious error)
1692 */
1693static int
1694check_tcp_remote (void *cls,
1695 const struct GNUNET_EXIT_TcpInternetStartMessage *start)
1696{
1697 struct ChannelState *state = cls;
1698
1699 if (NULL == state)
1700 {
1701 GNUNET_break_op (0);
1702 return GNUNET_SYSERR;
1703 }
1704 if (GNUNET_YES == state->is_dns)
1705 {
1706 GNUNET_break_op (0);
1707 return GNUNET_SYSERR;
1708 }
1709 if ((NULL != state->specifics.tcp_udp.serv) ||
1710 (NULL != state->specifics.tcp_udp.heap_node))
1711 {
1712 GNUNET_break_op (0);
1713 return GNUNET_SYSERR;
1714 }
1715 if (start->tcp_header.off * 4 < sizeof(struct GNUNET_TUN_TcpHeader))
1716 {
1717 GNUNET_break_op (0);
1718 return GNUNET_SYSERR;
1719 }
1720 return GNUNET_OK;
1721}
1722
1723
1724/**
1725 * Process a request to forward TCP data to the Internet via this peer.
1726 *
1727 * @param cls our `struct ChannelState *`
1728 * @param start the actual message
1729 */
1730static void
1731handle_tcp_remote (void *cls,
1732 const struct GNUNET_EXIT_TcpInternetStartMessage *start)
1733{
1734 struct ChannelState *state = cls;
1735 uint16_t pkt_len = ntohs (start->header.size) - sizeof(struct
1736 GNUNET_EXIT_TcpInternetStartMessage);
1737 const struct in_addr *v4;
1738 const struct in6_addr *v6;
1739 const void *payload;
1740 int af;
1741
1742 if (GNUNET_SYSERR == state->is_dns)
1743 {
1744 /* channel is UDP/TCP from now on */
1745 state->is_dns = GNUNET_NO;
1746 }
1747 GNUNET_STATISTICS_update (stats,
1748 gettext_noop ("# Bytes received from CADET"),
1749 pkt_len, GNUNET_NO);
1750 GNUNET_STATISTICS_update (stats,
1751 gettext_noop (
1752 "# TCP IP-exit creation requests received via cadet"),
1753 1, GNUNET_NO);
1754 af = (int) ntohl (start->af);
1755 state->specifics.tcp_udp.ri.remote_address.af = af;
1756 switch (af)
1757 {
1758 case AF_INET:
1759 if (pkt_len < sizeof(struct in_addr))
1760 {
1761 GNUNET_break_op (0);
1762 return;
1763 }
1764 if (! ipv4_exit)
1765 {
1766 GNUNET_break_op (0);
1767 return;
1768 }
1769 v4 = (const struct in_addr*) &start[1];
1770 payload = &v4[1];
1771 pkt_len -= sizeof(struct in_addr);
1772 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
1773 break;
1774
1775 case AF_INET6:
1776 if (pkt_len < sizeof(struct in6_addr))
1777 {
1778 GNUNET_break_op (0);
1779 return;
1780 }
1781 if (! ipv6_exit)
1782 {
1783 GNUNET_break_op (0);
1784 return;
1785 }
1786 v6 = (const struct in6_addr*) &start[1];
1787 payload = &v6[1];
1788 pkt_len -= sizeof(struct in6_addr);
1789 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
1790 break;
1791
1792 default:
1793 GNUNET_break_op (0);
1794 return;
1795 }
1796 {
1797 char buf[INET6_ADDRSTRLEN];
1798 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1799 "Received payload from %s for existing TCP stream to %s:%u\n",
1800 GNUNET_i2s (&state->peer),
1801 inet_ntop (af,
1802 &state->specifics.tcp_udp.ri.remote_address.address,
1803 buf, sizeof(buf)),
1804 (unsigned int) ntohs (start->tcp_header.destination_port));
1805 }
1806 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_TCP;
1807 state->specifics.tcp_udp.ri.remote_address.port = ntohs (
1808 start->tcp_header.destination_port);
1809 setup_state_record (state);
1810 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1811 &state->specifics.tcp_udp.ri.local_address,
1812 &start->tcp_header,
1813 payload,
1814 pkt_len);
1815 GNUNET_CADET_receive_done (state->channel);
1816}
1817
1818
1819/**
1820 * Check a request to forward TCP data on an established
1821 * connection via this peer.
1822 *
1823 * @param cls our `struct ChannelState *`
1824 * @param message the actual message
1825 * @return #GNUNET_OK to keep the connection open,
1826 * #GNUNET_SYSERR to close it (signal serious error)
1827 */
1828static int
1829check_tcp_data (void *cls,
1830 const struct GNUNET_EXIT_TcpDataMessage *data)
1831{
1832 struct ChannelState *state = cls;
1833
1834 if ((NULL == state) ||
1835 (NULL == state->specifics.tcp_udp.heap_node))
1836 {
1837 /* connection should have been up! */
1838 GNUNET_STATISTICS_update (stats,
1839 gettext_noop (
1840 "# TCP DATA requests dropped (no session)"),
1841 1, GNUNET_NO);
1842 GNUNET_break_op (0);
1843 return GNUNET_SYSERR;
1844 }
1845 if (data->tcp_header.off * 4 < sizeof(struct GNUNET_TUN_TcpHeader))
1846 {
1847 GNUNET_break_op (0);
1848 return GNUNET_SYSERR;
1849 }
1850 if (GNUNET_YES == state->is_dns)
1851 {
1852 GNUNET_break_op (0);
1853 return GNUNET_SYSERR;
1854 }
1855 return GNUNET_OK;
1856}
1857
1858
1859/**
1860 * Process a request to forward TCP data on an established
1861 * connection via this peer.
1862 *
1863 * @param cls our `struct ChannelState *`
1864 * @param message the actual message
1865 */
1866static void
1867handle_tcp_data (void *cls,
1868 const struct GNUNET_EXIT_TcpDataMessage *data)
1869{
1870 struct ChannelState *state = cls;
1871 uint16_t pkt_len = ntohs (data->header.size) - sizeof(struct
1872 GNUNET_EXIT_TcpDataMessage);
1873
1874 GNUNET_STATISTICS_update (stats,
1875 gettext_noop ("# Bytes received from CADET"),
1876 pkt_len, GNUNET_NO);
1877 GNUNET_STATISTICS_update (stats,
1878 gettext_noop (
1879 "# TCP data requests received via cadet"),
1880 1, GNUNET_NO);
1881 if (GNUNET_SYSERR == state->is_dns)
1882 {
1883 /* channel is UDP/TCP from now on */
1884 state->is_dns = GNUNET_NO;
1885 }
1886
1887 GNUNET_break_op (ntohl (data->reserved) == 0);
1888 {
1889 char buf[INET6_ADDRSTRLEN];
1890 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1891 "Received additional %u bytes of data from %s for TCP stream to %s:%u\n",
1892 pkt_len,
1893 GNUNET_i2s (&state->peer),
1894 inet_ntop (state->specifics.tcp_udp.ri.remote_address.af,
1895 &state->specifics.tcp_udp.ri.remote_address.address,
1896 buf, sizeof(buf)),
1897 (unsigned int) state->specifics.tcp_udp.ri.remote_address.port);
1898 }
1899
1900 send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
1901 &state->specifics.tcp_udp.ri.local_address,
1902 &data->tcp_header,
1903 &data[1], pkt_len);
1904 GNUNET_CADET_receive_done (state->channel);
1905}
1906
1907
1908/**
1909 * Synthesize a plausible ICMP payload for an ICMPv4 error
1910 * response on the given channel.
1911 *
1912 * @param state channel information
1913 * @param ipp IPv6 header to fill in (ICMP payload)
1914 * @param udp "UDP" header to fill in (ICMP payload); might actually
1915 * also be the first 8 bytes of the TCP header
1916 */
1917static void
1918make_up_icmpv4_payload (struct ChannelState *state,
1919 struct GNUNET_TUN_IPv4Header *ipp,
1920 struct GNUNET_TUN_UdpHeader *udp)
1921{
1922 GNUNET_TUN_initialize_ipv4_header (ipp,
1923 state->specifics.tcp_udp.ri.remote_address.
1924 proto,
1925 sizeof(struct GNUNET_TUN_TcpHeader),
1926 &state->specifics.tcp_udp.ri.remote_address
1927 .address.ipv4,
1928 &state->specifics.tcp_udp.ri.local_address.
1929 address.ipv4);
1930 udp->source_port = htons (state->specifics.tcp_udp.ri.remote_address.port);
1931 udp->destination_port = htons (
1932 state->specifics.tcp_udp.ri.local_address.port);
1933 udp->len = htons (0);
1934 udp->crc = htons (0);
1935}
1936
1937
1938/**
1939 * Synthesize a plausible ICMP payload for an ICMPv6 error
1940 * response on the given channel.
1941 *
1942 * @param state channel information
1943 * @param ipp IPv6 header to fill in (ICMP payload)
1944 * @param udp "UDP" header to fill in (ICMP payload); might actually
1945 * also be the first 8 bytes of the TCP header
1946 */
1947static void
1948make_up_icmpv6_payload (struct ChannelState *state,
1949 struct GNUNET_TUN_IPv6Header *ipp,
1950 struct GNUNET_TUN_UdpHeader *udp)
1951{
1952 GNUNET_TUN_initialize_ipv6_header (ipp,
1953 state->specifics.tcp_udp.ri.remote_address.
1954 proto,
1955 sizeof(struct GNUNET_TUN_TcpHeader),
1956 &state->specifics.tcp_udp.ri.remote_address
1957 .address.ipv6,
1958 &state->specifics.tcp_udp.ri.local_address.
1959 address.ipv6);
1960 udp->source_port = htons (state->specifics.tcp_udp.ri.remote_address.port);
1961 udp->destination_port = htons (
1962 state->specifics.tcp_udp.ri.local_address.port);
1963 udp->len = htons (0);
1964 udp->crc = htons (0);
1965}
1966
1967
1968/**
1969 * Check a request to forward ICMP data to the Internet via this peer.
1970 *
1971 * @param cls our `struct ChannelState *`
1972 * @param msg the actual message
1973 * @return #GNUNET_OK to keep the connection open,
1974 * #GNUNET_SYSERR to close it (signal serious error)
1975 */
1976static int
1977check_icmp_remote (void *cls,
1978 const struct GNUNET_EXIT_IcmpInternetMessage *msg)
1979{
1980 struct ChannelState *state = cls;
1981
1982 if (GNUNET_YES == state->is_dns)
1983 {
1984 GNUNET_break_op (0);
1985 return GNUNET_SYSERR;
1986 }
1987 return GNUNET_OK;
1988}
1989
1990
1991/**
1992 * Process a request to forward ICMP data to the Internet via this peer.
1993 *
1994 * @param cls our `struct ChannelState *`
1995 * @param msg the actual message
1996 */
1997static void
1998handle_icmp_remote (void *cls,
1999 const struct GNUNET_EXIT_IcmpInternetMessage *msg)
2000{
2001 struct ChannelState *state = cls;
2002 uint16_t pkt_len = ntohs (msg->header.size) - sizeof(struct
2003 GNUNET_EXIT_IcmpInternetMessage);
2004 const struct in_addr *v4;
2005 const struct in6_addr *v6;
2006 const void *payload;
2007 char buf[sizeof(struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2008 int af;
2009
2010 if (GNUNET_SYSERR == state->is_dns)
2011 {
2012 /* channel is UDP/TCP from now on */
2013 state->is_dns = GNUNET_NO;
2014 }
2015 GNUNET_STATISTICS_update (stats,
2016 gettext_noop ("# Bytes received from CADET"),
2017 pkt_len, GNUNET_NO);
2018 GNUNET_STATISTICS_update (stats,
2019 gettext_noop (
2020 "# ICMP IP-exit requests received via cadet"),
2021 1, GNUNET_NO);
2022
2023 af = (int) ntohl (msg->af);
2024 if ((NULL != state->specifics.tcp_udp.heap_node) &&
2025 (af != state->specifics.tcp_udp.ri.remote_address.af))
2026 {
2027 /* other peer switched AF on this channel; not allowed */
2028 GNUNET_break_op (0);
2029 return;
2030 }
2031
2032 switch (af)
2033 {
2034 case AF_INET:
2035 if (pkt_len < sizeof(struct in_addr))
2036 {
2037 GNUNET_break_op (0);
2038 return;
2039 }
2040 if (! ipv4_exit)
2041 {
2042 GNUNET_break_op (0);
2043 return;
2044 }
2045 v4 = (const struct in_addr*) &msg[1];
2046 payload = &v4[1];
2047 pkt_len -= sizeof(struct in_addr);
2048 state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
2049 if (NULL == state->specifics.tcp_udp.heap_node)
2050 {
2051 state->specifics.tcp_udp.ri.remote_address.af = af;
2052 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_ICMP;
2053 setup_state_record (state);
2054 }
2055 /* check that ICMP type is something we want to support
2056 and possibly make up payload! */
2057 switch (msg->icmp_header.type)
2058 {
2059 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2060 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2061 break;
2062
2063 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2064 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2065 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2066 if (0 != pkt_len)
2067 {
2068 GNUNET_break_op (0);
2069 return;
2070 }
2071 /* make up payload */
2072 {
2073 struct GNUNET_TUN_IPv4Header *ipp = (struct
2074 GNUNET_TUN_IPv4Header *) buf;
2075 struct GNUNET_TUN_UdpHeader *udp = (struct
2076 GNUNET_TUN_UdpHeader *) &ipp[1];
2077
2078 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
2079 pkt_len = sizeof(struct GNUNET_TUN_IPv4Header) + 8;
2080 make_up_icmpv4_payload (state,
2081 ipp,
2082 udp);
2083 payload = ipp;
2084 }
2085 break;
2086
2087 default:
2088 GNUNET_break_op (0);
2089 GNUNET_STATISTICS_update (stats,
2090 gettext_noop (
2091 "# ICMPv4 packets dropped (type not allowed)"),
2092 1, GNUNET_NO);
2093 return;
2094 }
2095 /* end AF_INET */
2096 break;
2097
2098 case AF_INET6:
2099 if (pkt_len < sizeof(struct in6_addr))
2100 {
2101 GNUNET_break_op (0);
2102 return;
2103 }
2104 if (! ipv6_exit)
2105 {
2106 GNUNET_break_op (0);
2107 return;
2108 }
2109 v6 = (const struct in6_addr*) &msg[1];
2110 payload = &v6[1];
2111 pkt_len -= sizeof(struct in6_addr);
2112 state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
2113 if (NULL == state->specifics.tcp_udp.heap_node)
2114 {
2115 state->specifics.tcp_udp.ri.remote_address.af = af;
2116 state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_ICMPV6;
2117 setup_state_record (state);
2118 }
2119 /* check that ICMP type is something we want to support
2120 and possibly make up payload! */
2121 switch (msg->icmp_header.type)
2122 {
2123 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2124 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2125 break;
2126
2127 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2128 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2129 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2130 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2131 if (0 != pkt_len)
2132 {
2133 GNUNET_break_op (0);
2134 return;
2135 }
2136 /* make up payload */
2137 {
2138 struct GNUNET_TUN_IPv6Header *ipp = (struct
2139 GNUNET_TUN_IPv6Header *) buf;
2140 struct GNUNET_TUN_UdpHeader *udp = (struct
2141 GNUNET_TUN_UdpHeader *) &ipp[1];
2142
2143 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
2144 pkt_len = sizeof(struct GNUNET_TUN_IPv6Header) + 8;
2145 make_up_icmpv6_payload (state,
2146 ipp,
2147 udp);
2148 payload = ipp;
2149 }
2150 break;
2151
2152 default:
2153 GNUNET_break_op (0);
2154 GNUNET_STATISTICS_update (stats,
2155 gettext_noop (
2156 "# ICMPv6 packets dropped (type not allowed)"),
2157 1, GNUNET_NO);
2158 return;
2159 }
2160 /* end AF_INET6 */
2161 break;
2162
2163 default:
2164 /* bad AF */
2165 GNUNET_break_op (0);
2166 return;
2167 }
2168
2169 {
2170 char buf[INET6_ADDRSTRLEN];
2171 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2172 "Received ICMP data from %s for forwarding to %s\n",
2173 GNUNET_i2s (&state->peer),
2174 inet_ntop (af,
2175 &state->specifics.tcp_udp.ri.remote_address.address,
2176 buf, sizeof(buf)));
2177 }
2178 send_icmp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2179 &state->specifics.tcp_udp.ri.local_address,
2180 &msg->icmp_header,
2181 payload, pkt_len);
2182 GNUNET_CADET_receive_done (state->channel);
2183}
2184
2185
2186/**
2187 * Setup ICMP payload for ICMP error messages. Called
2188 * for both IPv4 and IPv6 addresses.
2189 *
2190 * @param state context for creating the IP Packet
2191 * @param buf where to create the payload, has at least
2192 * sizeof (struct GNUNET_TUN_IPv6Header) + 8 bytes
2193 * @return number of bytes of payload we created in buf
2194 */
2195static uint16_t
2196make_up_icmp_service_payload (struct ChannelState *state,
2197 char *buf)
2198{
2199 switch (state->specifics.tcp_udp.serv->address.af)
2200 {
2201 case AF_INET:
2202 {
2203 struct GNUNET_TUN_IPv4Header *ipv4;
2204 struct GNUNET_TUN_UdpHeader *udp;
2205
2206 ipv4 = (struct GNUNET_TUN_IPv4Header *) buf;
2207 udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2208 make_up_icmpv4_payload (state,
2209 ipv4,
2210 udp);
2211 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
2212 return sizeof(struct GNUNET_TUN_IPv4Header) + 8;
2213 }
2214 break;
2215
2216 case AF_INET6:
2217 {
2218 struct GNUNET_TUN_IPv6Header *ipv6;
2219 struct GNUNET_TUN_UdpHeader *udp;
2220
2221 ipv6 = (struct GNUNET_TUN_IPv6Header *) buf;
2222 udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2223 make_up_icmpv6_payload (state,
2224 ipv6,
2225 udp);
2226 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
2227 return sizeof(struct GNUNET_TUN_IPv6Header) + 8;
2228 }
2229 break;
2230
2231 default:
2232 GNUNET_break (0);
2233 }
2234 return 0;
2235}
2236
2237
2238/**
2239 * Check a request via cadet to send ICMP data to a service
2240 * offered by this system.
2241 *
2242 * @param cls our `struct ChannelState *`
2243 * @param msg the actual message
2244 * @return #GNUNET_OK to keep the connection open,
2245 * #GNUNET_SYSERR to close it (signal serious error)
2246 */
2247static int
2248check_icmp_service (void *cls,
2249 const struct GNUNET_EXIT_IcmpServiceMessage *msg)
2250{
2251 struct ChannelState *state = cls;
2252
2253 if (GNUNET_YES == state->is_dns)
2254 {
2255 GNUNET_break_op (0);
2256 return GNUNET_SYSERR;
2257 }
2258 if (NULL == state->specifics.tcp_udp.serv)
2259 {
2260 GNUNET_break_op (0);
2261 return GNUNET_SYSERR;
2262 }
2263 return GNUNET_OK;
2264}
2265
2266
2267/**
2268 * Process a request via cadet to send ICMP data to a service
2269 * offered by this system.
2270 *
2271 * @param cls our `struct ChannelState *`
2272 * @param msg the actual message
2273 */
2274static void
2275handle_icmp_service (void *cls,
2276 const struct GNUNET_EXIT_IcmpServiceMessage *msg)
2277{
2278 struct ChannelState *state = cls;
2279 uint16_t pkt_len = ntohs (msg->header.size) - sizeof(struct
2280 GNUNET_EXIT_IcmpServiceMessage);
2281 struct GNUNET_TUN_IcmpHeader icmp;
2282 char buf[sizeof(struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2283 const void *payload;
2284
2285 GNUNET_STATISTICS_update (stats,
2286 gettext_noop ("# Bytes received from CADET"),
2287 pkt_len, GNUNET_NO);
2288 GNUNET_STATISTICS_update (stats,
2289 gettext_noop (
2290 "# ICMP service requests received via cadet"),
2291 1, GNUNET_NO);
2292 /* check that we got at least a valid header */
2293 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2294 "Received data from %s for forwarding to ICMP service %s\n",
2295 GNUNET_i2s (&state->peer),
2296 GNUNET_h2s (&state->specifics.tcp_udp.serv->descriptor));
2297 icmp = msg->icmp_header;
2298 payload = &msg[1];
2299 state->specifics.tcp_udp.ri.remote_address
2300 = state->specifics.tcp_udp.serv->address;
2301 setup_state_record (state);
2302
2303 /* check that ICMP type is something we want to support,
2304 perform ICMP PT if needed and possibly make up payload */
2305 switch (msg->af)
2306 {
2307 case AF_INET:
2308 switch (msg->icmp_header.type)
2309 {
2310 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2311 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2312 icmp.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
2313 break;
2314
2315 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2316 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2317 icmp.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
2318 break;
2319
2320 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2321 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2322 icmp.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
2323 if (0 != pkt_len)
2324 {
2325 GNUNET_break_op (0);
2326 return;
2327 }
2328 payload = buf;
2329 pkt_len = make_up_icmp_service_payload (state, buf);
2330 break;
2331
2332 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2333 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2334 icmp.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
2335 if (0 != pkt_len)
2336 {
2337 GNUNET_break_op (0);
2338 return;
2339 }
2340 payload = buf;
2341 pkt_len = make_up_icmp_service_payload (state, buf);
2342 break;
2343
2344 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2345 if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2346 {
2347 GNUNET_STATISTICS_update (stats,
2348 gettext_noop (
2349 "# ICMPv4 packets dropped (impossible PT to v6)"),
2350 1, GNUNET_NO);
2351 return;
2352 }
2353 if (0 != pkt_len)
2354 {
2355 GNUNET_break_op (0);
2356 return;
2357 }
2358 payload = buf;
2359 pkt_len = make_up_icmp_service_payload (state, buf);
2360 break;
2361
2362 default:
2363 GNUNET_break_op (0);
2364 GNUNET_STATISTICS_update (stats,
2365 gettext_noop (
2366 "# ICMPv4 packets dropped (type not allowed)"),
2367 1, GNUNET_NO);
2368 return;
2369 }
2370 /* end of AF_INET */
2371 break;
2372
2373 case AF_INET6:
2374 switch (msg->icmp_header.type)
2375 {
2376 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2377 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2378 icmp.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
2379 break;
2380
2381 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2382 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2383 icmp.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
2384 break;
2385
2386 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2387 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2388 icmp.type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
2389 if (0 != pkt_len)
2390 {
2391 GNUNET_break_op (0);
2392 return;
2393 }
2394 payload = buf;
2395 pkt_len = make_up_icmp_service_payload (state, buf);
2396 break;
2397
2398 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2399 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2400 icmp.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
2401 if (0 != pkt_len)
2402 {
2403 GNUNET_break_op (0);
2404 return;
2405 }
2406 payload = buf;
2407 pkt_len = make_up_icmp_service_payload (state, buf);
2408 break;
2409
2410 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2411 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2412 if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2413 {
2414 GNUNET_STATISTICS_update (stats,
2415 gettext_noop (
2416 "# ICMPv6 packets dropped (impossible PT to v4)"),
2417 1, GNUNET_NO);
2418 return;
2419 }
2420 if (0 != pkt_len)
2421 {
2422 GNUNET_break_op (0);
2423 return;
2424 }
2425 payload = buf;
2426 pkt_len = make_up_icmp_service_payload (state, buf);
2427 break;
2428
2429 default:
2430 GNUNET_break_op (0);
2431 GNUNET_STATISTICS_update (stats,
2432 gettext_noop (
2433 "# ICMPv6 packets dropped (type not allowed)"),
2434 1, GNUNET_NO);
2435 return;
2436 }
2437 /* end of AF_INET6 */
2438 break;
2439
2440 default:
2441 GNUNET_break_op (0);
2442 return;
2443 }
2444
2445 send_icmp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2446 &state->specifics.tcp_udp.ri.local_address,
2447 &icmp,
2448 payload,
2449 pkt_len);
2450 GNUNET_CADET_receive_done (state->channel);
2451}
2452
2453
2454/**
2455 * Free memory associated with a service record.
2456 *
2457 * @param cls unused
2458 * @param key service descriptor
2459 * @param value service record to free
2460 * @return #GNUNET_OK
2461 */
2462static int
2463free_service_record (void *cls,
2464 const struct GNUNET_HashCode *key,
2465 void *value)
2466{
2467 struct LocalService *service = value;
2468
2469 GNUNET_assert (GNUNET_YES ==
2470 GNUNET_CONTAINER_multihashmap_remove (services,
2471 key,
2472 service));
2473 GNUNET_CADET_close_port (service->port);
2474 GNUNET_free (service->name);
2475 GNUNET_free (service);
2476 return GNUNET_OK;
2477}
2478
2479
2480/**
2481 * Callback from CADET for new channels.
2482 *
2483 * @param cls closure
2484 * @param channel new handle to the channel
2485 * @param initiator peer that started the channel
2486 * @return initial channel context for the channel
2487 */
2488static void *
2489new_service_channel (void *cls,
2490 struct GNUNET_CADET_Channel *channel,
2491 const struct GNUNET_PeerIdentity *initiator)
2492{
2493 struct LocalService *ls = cls;
2494 struct ChannelState *s = GNUNET_new (struct ChannelState);
2495
2496 s->peer = *initiator;
2497 GNUNET_STATISTICS_update (stats,
2498 gettext_noop ("# Inbound CADET channels created"),
2499 1,
2500 GNUNET_NO);
2501 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2502 "Received inbound channel from `%s'\n",
2503 GNUNET_i2s (initiator));
2504 s->channel = channel;
2505 s->specifics.tcp_udp.serv = ls;
2506 s->specifics.tcp_udp.ri.remote_address = ls->address;
2507 return s;
2508}
2509
2510
2511/**
2512 * Function called by cadet whenever an inbound channel is destroyed.
2513 * Should clean up any associated state.
2514 *
2515 * @param cls our `struct ChannelState *`
2516 * @param channel connection to the other end (henceforth invalid)
2517 */
2518static void
2519clean_channel (void *cls,
2520 const struct GNUNET_CADET_Channel *channel)
2521{
2522 struct ChannelState *s = cls;
2523
2524 LOG (GNUNET_ERROR_TYPE_DEBUG,
2525 "Channel destroyed\n");
2526 if (GNUNET_SYSERR == s->is_dns)
2527 {
2528 GNUNET_free (s);
2529 return;
2530 }
2531 if (GNUNET_YES == s->is_dns)
2532 {
2533 if (channels[s->specifics.dns.my_id] == s)
2534 channels[s->specifics.dns.my_id] = NULL;
2535 }
2536 else
2537 {
2538 if (NULL != s->specifics.tcp_udp.heap_node)
2539 {
2540 GNUNET_assert (GNUNET_YES ==
2541 GNUNET_CONTAINER_multihashmap_remove (connections_map,
2542 &s->specifics.tcp_udp
2543 .state_key,
2544 s));
2545 GNUNET_CONTAINER_heap_remove_node (s->specifics.tcp_udp.heap_node);
2546 s->specifics.tcp_udp.heap_node = NULL;
2547 }
2548 }
2549 GNUNET_free (s);
2550}
2551
2552
2553/**
2554 * Given a service descriptor and a destination port, find the
2555 * respective service entry.
2556 *
2557 * @param proto IPPROTO_TCP or IPPROTO_UDP
2558 * @param name name of the service
2559 * @param destination_port destination port
2560 * @param service service information record to store (service->name will be set).
2561 */
2562static void
2563store_service (int proto,
2564 const char *name,
2565 uint16_t destination_port,
2566 struct LocalService *service)
2567{
2568 struct GNUNET_MQ_MessageHandler handlers[] = {
2569 GNUNET_MQ_hd_var_size (icmp_service,
2570 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE,
2571 struct GNUNET_EXIT_IcmpServiceMessage,
2572 service),
2573 GNUNET_MQ_hd_var_size (udp_service,
2574 GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE,
2575 struct GNUNET_EXIT_UdpServiceMessage,
2576 service),
2577 GNUNET_MQ_hd_var_size (tcp_service,
2578 GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START,
2579 struct GNUNET_EXIT_TcpServiceStartMessage,
2580 service),
2581 GNUNET_MQ_hd_var_size (tcp_data,
2582 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT,
2583 struct GNUNET_EXIT_TcpDataMessage,
2584 service),
2585 GNUNET_MQ_handler_end ()
2586 };
2587
2588 struct GNUNET_HashCode cadet_port;
2589
2590 service->name = GNUNET_strdup (name);
2591 GNUNET_TUN_service_name_to_hash (name,
2592 &service->descriptor);
2593 GNUNET_TUN_compute_service_cadet_port (&service->descriptor,
2594 destination_port,
2595 &cadet_port);
2596 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2597 "Opening CADET port %s for SERVICE exit %s on port %u\n",
2598 GNUNET_h2s (&cadet_port),
2599 name,
2600 (unsigned int) destination_port);
2601 service->port = GNUNET_CADET_open_port (cadet_handle,
2602 &cadet_port,
2603 &new_service_channel,
2604 service,
2605 NULL,
2606 &clean_channel,
2607 handlers);
2608 service->is_udp = (IPPROTO_UDP == proto);
2609 if (GNUNET_OK !=
2610 GNUNET_CONTAINER_multihashmap_put (services,
2611 &cadet_port,
2612 service,
2613 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
2614 {
2615 GNUNET_CADET_close_port (service->port);
2616 GNUNET_free (service->name);
2617 GNUNET_free (service);
2618 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2619 _ ("Got duplicate service records for `%s:%u'\n"),
2620 name,
2621 (unsigned int) destination_port);
2622 }
2623}
2624
2625
2626/**
2627 * Send the given packet via the cadet channel.
2628 *
2629 * @param s channel destination
2630 * @param env message to queue
2631 */
2632static void
2633send_packet_to_cadet_channel (struct ChannelState *s,
2634 struct GNUNET_MQ_Envelope *env)
2635{
2636 GNUNET_assert (NULL != s);
2637 GNUNET_STATISTICS_update (stats,
2638 gettext_noop (
2639 "# Messages transmitted via cadet channels"),
2640 1,
2641 GNUNET_NO);
2642 GNUNET_MQ_send (GNUNET_CADET_get_mq (s->channel),
2643 env);
2644}
2645
2646
2647/**
2648 * @brief Handles an ICMP packet received from the helper.
2649 *
2650 * @param icmp A pointer to the Packet
2651 * @param pktlen number of bytes in @a icmp
2652 * @param af address family (AFINET or AF_INET6)
2653 * @param destination_ip destination IP-address of the IP packet (should
2654 * be our local address)
2655 * @param source_ip original source IP-address of the IP packet (should
2656 * be the original destination address)
2657 */
2658static void
2659icmp_from_helper (const struct GNUNET_TUN_IcmpHeader *icmp,
2660 size_t pktlen,
2661 int af,
2662 const void *destination_ip,
2663 const void *source_ip)
2664{
2665 struct ChannelState *state;
2666 struct GNUNET_MQ_Envelope *env;
2667 struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
2668 const struct GNUNET_TUN_IPv4Header *ipv4;
2669 const struct GNUNET_TUN_IPv6Header *ipv6;
2670 const struct GNUNET_TUN_UdpHeader *udp;
2671 uint16_t source_port;
2672 uint16_t destination_port;
2673 uint8_t protocol;
2674
2675 {
2676 char sbuf[INET6_ADDRSTRLEN];
2677 char dbuf[INET6_ADDRSTRLEN];
2678 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2679 "Received ICMP packet going from %s to %s\n",
2680 inet_ntop (af,
2681 source_ip,
2682 sbuf, sizeof(sbuf)),
2683 inet_ntop (af,
2684 destination_ip,
2685 dbuf, sizeof(dbuf)));
2686 }
2687
2688 if (pktlen < sizeof(struct GNUNET_TUN_IcmpHeader))
2689 {
2690 /* blame kernel */
2691 GNUNET_break (0);
2692 return;
2693 }
2694
2695 /* Find out if this is an ICMP packet in response to an existing
2696 TCP/UDP packet and if so, figure out ports / protocol of the
2697 existing session from the IP data in the ICMP payload */
2698 source_port = 0;
2699 destination_port = 0;
2700 switch (af)
2701 {
2702 case AF_INET:
2703 protocol = IPPROTO_ICMP;
2704 switch (icmp->type)
2705 {
2706 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2707 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2708 break;
2709
2710 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2711 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2712 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2713 if (pktlen <
2714 sizeof(struct GNUNET_TUN_IcmpHeader)
2715 + sizeof(struct GNUNET_TUN_IPv4Header) + 8)
2716 {
2717 /* blame kernel */
2718 GNUNET_break (0);
2719 return;
2720 }
2721 ipv4 = (const struct GNUNET_TUN_IPv4Header *) &icmp[1];
2722 protocol = ipv4->protocol;
2723 /* could be TCP or UDP, but both have the ports in the right
2724 place, so that doesn't matter here */
2725 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2726 /* swap ports, as they are from the original message */
2727 destination_port = ntohs (udp->source_port);
2728 source_port = ntohs (udp->destination_port);
2729 /* throw away ICMP payload, won't be useful for the other side anyway */
2730 pktlen = sizeof(struct GNUNET_TUN_IcmpHeader);
2731 break;
2732
2733 default:
2734 GNUNET_STATISTICS_update (stats,
2735 gettext_noop (
2736 "# ICMPv4 packets dropped (type not allowed)"),
2737 1, GNUNET_NO);
2738 return;
2739 }
2740 break;
2741
2742 case AF_INET6:
2743 protocol = IPPROTO_ICMPV6;
2744 switch (icmp->type)
2745 {
2746 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2747 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2748 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2749 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2750 if (pktlen <
2751 sizeof(struct GNUNET_TUN_IcmpHeader)
2752 + sizeof(struct GNUNET_TUN_IPv6Header) + 8)
2753 {
2754 /* blame kernel */
2755 GNUNET_break (0);
2756 return;
2757 }
2758 ipv6 = (const struct GNUNET_TUN_IPv6Header *) &icmp[1];
2759 protocol = ipv6->next_header;
2760 /* could be TCP or UDP, but both have the ports in the right
2761 place, so that doesn't matter here */
2762 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2763 /* swap ports, as they are from the original message */
2764 destination_port = ntohs (udp->source_port);
2765 source_port = ntohs (udp->destination_port);
2766 /* throw away ICMP payload, won't be useful for the other side anyway */
2767 pktlen = sizeof(struct GNUNET_TUN_IcmpHeader);
2768 break;
2769
2770 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2771 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2772 break;
2773
2774 default:
2775 GNUNET_STATISTICS_update (stats,
2776 gettext_noop (
2777 "# ICMPv6 packets dropped (type not allowed)"),
2778 1, GNUNET_NO);
2779 return;
2780 }
2781 break;
2782
2783 default:
2784 GNUNET_assert (0);
2785 }
2786 switch (protocol)
2787 {
2788 case IPPROTO_ICMP:
2789 state = get_redirect_state (af,
2790 IPPROTO_ICMP,
2791 source_ip,
2792 0,
2793 destination_ip,
2794 0,
2795 NULL);
2796 break;
2797
2798 case IPPROTO_ICMPV6:
2799 state = get_redirect_state (af,
2800 IPPROTO_ICMPV6,
2801 source_ip,
2802 0,
2803 destination_ip,
2804 0,
2805 NULL);
2806 break;
2807
2808 case IPPROTO_UDP:
2809 state = get_redirect_state (af,
2810 IPPROTO_UDP,
2811 source_ip,
2812 source_port,
2813 destination_ip,
2814 destination_port,
2815 NULL);
2816 break;
2817
2818 case IPPROTO_TCP:
2819 state = get_redirect_state (af,
2820 IPPROTO_TCP,
2821 source_ip,
2822 source_port,
2823 destination_ip,
2824 destination_port,
2825 NULL);
2826 break;
2827
2828 default:
2829 GNUNET_STATISTICS_update (stats,
2830 gettext_noop (
2831 "# ICMP packets dropped (not allowed)"),
2832 1,
2833 GNUNET_NO);
2834 return;
2835 }
2836 if (NULL == state)
2837 {
2838 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2839 _ (
2840 "ICMP Packet dropped, have no matching connection information\n"));
2841 return;
2842 }
2843 env = GNUNET_MQ_msg_extra (i2v,
2844 pktlen - sizeof(struct GNUNET_TUN_IcmpHeader),
2845 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN);
2846 i2v->af = htonl (af);
2847 GNUNET_memcpy (&i2v->icmp_header,
2848 icmp,
2849 pktlen);
2850 send_packet_to_cadet_channel (state,
2851 env);
2852}
2853
2854
2855/**
2856 * @brief Handles an UDP packet received from the helper.
2857 *
2858 * @param udp A pointer to the Packet
2859 * @param pktlen number of bytes in 'udp'
2860 * @param af address family (AFINET or AF_INET6)
2861 * @param destination_ip destination IP-address of the IP packet (should
2862 * be our local address)
2863 * @param source_ip original source IP-address of the IP packet (should
2864 * be the original destination address)
2865 */
2866static void
2867udp_from_helper (const struct GNUNET_TUN_UdpHeader *udp,
2868 size_t pktlen,
2869 int af,
2870 const void *destination_ip,
2871 const void *source_ip)
2872{
2873 struct ChannelState *state;
2874 struct GNUNET_MQ_Envelope *env;
2875 struct GNUNET_EXIT_UdpReplyMessage *urm;
2876
2877 {
2878 char sbuf[INET6_ADDRSTRLEN];
2879 char dbuf[INET6_ADDRSTRLEN];
2880
2881 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2882 "Received UDP packet going from %s:%u to %s:%u\n",
2883 inet_ntop (af,
2884 source_ip,
2885 sbuf, sizeof(sbuf)),
2886 (unsigned int) ntohs (udp->source_port),
2887 inet_ntop (af,
2888 destination_ip,
2889 dbuf, sizeof(dbuf)),
2890 (unsigned int) ntohs (udp->destination_port));
2891 }
2892
2893 if (pktlen < sizeof(struct GNUNET_TUN_UdpHeader))
2894 {
2895 /* blame kernel */
2896 GNUNET_break (0);
2897 return;
2898 }
2899 if (pktlen != ntohs (udp->len))
2900 {
2901 /* blame kernel */
2902 GNUNET_break (0);
2903 return;
2904 }
2905 state = get_redirect_state (af,
2906 IPPROTO_UDP,
2907 source_ip,
2908 ntohs (udp->source_port),
2909 destination_ip,
2910 ntohs (udp->destination_port),
2911 NULL);
2912 if (NULL == state)
2913 {
2914 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2915 _ (
2916 "UDP Packet dropped, have no matching connection information\n"));
2917 return;
2918 }
2919 env = GNUNET_MQ_msg_extra (urm,
2920 pktlen - sizeof(struct GNUNET_TUN_UdpHeader),
2921 GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY);
2922 urm->source_port = htons (0);
2923 urm->destination_port = htons (0);
2924 GNUNET_memcpy (&urm[1],
2925 &udp[1],
2926 pktlen - sizeof(struct GNUNET_TUN_UdpHeader));
2927 send_packet_to_cadet_channel (state,
2928 env);
2929}
2930
2931
2932/**
2933 * @brief Handles a TCP packet received from the helper.
2934 *
2935 * @param tcp A pointer to the Packet
2936 * @param pktlen the length of the packet, including its TCP header
2937 * @param af address family (AFINET or AF_INET6)
2938 * @param destination_ip destination IP-address of the IP packet (should
2939 * be our local address)
2940 * @param source_ip original source IP-address of the IP packet (should
2941 * be the original destination address)
2942 */
2943static void
2944tcp_from_helper (const struct GNUNET_TUN_TcpHeader *tcp,
2945 size_t pktlen,
2946 int af,
2947 const void *destination_ip,
2948 const void *source_ip)
2949{
2950 struct ChannelState *state;
2951 char buf[pktlen] GNUNET_ALIGN;
2952 struct GNUNET_TUN_TcpHeader *mtcp;
2953 struct GNUNET_EXIT_TcpDataMessage *tdm;
2954 struct GNUNET_MQ_Envelope *env;
2955 size_t mlen;
2956
2957 {
2958 char sbuf[INET6_ADDRSTRLEN];
2959 char dbuf[INET6_ADDRSTRLEN];
2960 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2961 "Received TCP packet with %u bytes going from %s:%u to %s:%u\n",
2962 (unsigned int) (pktlen - sizeof(struct GNUNET_TUN_TcpHeader)),
2963 inet_ntop (af,
2964 source_ip,
2965 sbuf, sizeof(sbuf)),
2966 (unsigned int) ntohs (tcp->source_port),
2967 inet_ntop (af,
2968 destination_ip,
2969 dbuf, sizeof(dbuf)),
2970 (unsigned int) ntohs (tcp->destination_port));
2971 }
2972
2973 if (pktlen < sizeof(struct GNUNET_TUN_TcpHeader))
2974 {
2975 /* blame kernel */
2976 GNUNET_break (0);
2977 return;
2978 }
2979 state = get_redirect_state (af,
2980 IPPROTO_TCP,
2981 source_ip,
2982 ntohs (tcp->source_port),
2983 destination_ip,
2984 ntohs (tcp->destination_port),
2985 NULL);
2986 if (NULL == state)
2987 {
2988 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2989 _ (
2990 "TCP Packet dropped, have no matching connection information\n"));
2991
2992 return;
2993 }
2994 /* mug port numbers and crc to avoid information leakage;
2995 sender will need to lookup the correct values anyway */
2996 GNUNET_memcpy (buf, tcp, pktlen);
2997 mtcp = (struct GNUNET_TUN_TcpHeader *) buf;
2998 mtcp->source_port = 0;
2999 mtcp->destination_port = 0;
3000 mtcp->crc = 0;
3001
3002 mlen = sizeof(struct GNUNET_EXIT_TcpDataMessage) + (pktlen - sizeof(struct
3003 GNUNET_TUN_TcpHeader));
3004 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
3005 {
3006 GNUNET_break (0);
3007 return;
3008 }
3009 env = GNUNET_MQ_msg_extra (tdm,
3010 pktlen - sizeof(struct GNUNET_TUN_TcpHeader),
3011 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN);
3012 tdm->reserved = htonl (0);
3013 GNUNET_memcpy (&tdm->tcp_header,
3014 buf,
3015 pktlen);
3016 send_packet_to_cadet_channel (state,
3017 env);
3018}
3019
3020
3021/**
3022 * Receive packets from the helper-process
3023 *
3024 * @param cls unused
3025 * @param message message received from helper
3026 */
3027static int
3028message_token (void *cls GNUNET_UNUSED,
3029 const struct GNUNET_MessageHeader *message)
3030{
3031 const struct GNUNET_TUN_Layer2PacketHeader *pkt_tun;
3032 size_t size;
3033
3034 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3035 "Got %u-byte message of type %u from gnunet-helper-exit\n",
3036 ntohs (message->size),
3037 ntohs (message->type));
3038 GNUNET_STATISTICS_update (stats,
3039 gettext_noop ("# Packets received from TUN"),
3040 1, GNUNET_NO);
3041 if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
3042 {
3043 GNUNET_break (0);
3044 return GNUNET_OK;
3045 }
3046 size = ntohs (message->size);
3047 if (size < sizeof(struct GNUNET_TUN_Layer2PacketHeader) + sizeof(struct
3048 GNUNET_MessageHeader))
3049 {
3050 GNUNET_break (0);
3051 return GNUNET_OK;
3052 }
3053 GNUNET_STATISTICS_update (stats,
3054 gettext_noop ("# Bytes received from TUN"),
3055 size, GNUNET_NO);
3056 pkt_tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
3057 size -= sizeof(struct GNUNET_TUN_Layer2PacketHeader) + sizeof(struct
3058 GNUNET_MessageHeader);
3059 switch (ntohs (pkt_tun->proto))
3060 {
3061 case ETH_P_IPV4:
3062 {
3063 const struct GNUNET_TUN_IPv4Header *pkt4;
3064
3065 if (size < sizeof(struct GNUNET_TUN_IPv4Header))
3066 {
3067 /* Kernel to blame? */
3068 GNUNET_break (0);
3069 return GNUNET_OK;
3070 }
3071 pkt4 = (const struct GNUNET_TUN_IPv4Header *) &pkt_tun[1];
3072 if (size != ntohs (pkt4->total_length))
3073 {
3074 /* Kernel to blame? */
3075 GNUNET_break (0);
3076 return GNUNET_OK;
3077 }
3078 if (pkt4->header_length * 4 != sizeof(struct GNUNET_TUN_IPv4Header))
3079 {
3080 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3081 _ ("IPv4 packet options received. Ignored.\n"));
3082 return GNUNET_OK;
3083 }
3084
3085 size -= sizeof(struct GNUNET_TUN_IPv4Header);
3086 switch (pkt4->protocol)
3087 {
3088 case IPPROTO_UDP:
3089 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt4[1], size,
3090 AF_INET,
3091 &pkt4->destination_address,
3092 &pkt4->source_address);
3093 break;
3094
3095 case IPPROTO_TCP:
3096 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt4[1], size,
3097 AF_INET,
3098 &pkt4->destination_address,
3099 &pkt4->source_address);
3100 break;
3101
3102 case IPPROTO_ICMP:
3103 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt4[1], size,
3104 AF_INET,
3105 &pkt4->destination_address,
3106 &pkt4->source_address);
3107 break;
3108
3109 default:
3110 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3111 _ (
3112 "IPv4 packet with unsupported next header %u received. Ignored.\n"),
3113 (int) pkt4->protocol);
3114 return GNUNET_OK;
3115 }
3116 }
3117 break;
3118
3119 case ETH_P_IPV6:
3120 {
3121 const struct GNUNET_TUN_IPv6Header *pkt6;
3122
3123 if (size < sizeof(struct GNUNET_TUN_IPv6Header))
3124 {
3125 /* Kernel to blame? */
3126 GNUNET_break (0);
3127 return GNUNET_OK;
3128 }
3129 pkt6 = (struct GNUNET_TUN_IPv6Header *) &pkt_tun[1];
3130 if (size != ntohs (pkt6->payload_length) + sizeof(struct
3131 GNUNET_TUN_IPv6Header))
3132 {
3133 /* Kernel to blame? */
3134 GNUNET_break (0);
3135 return GNUNET_OK;
3136 }
3137 size -= sizeof(struct GNUNET_TUN_IPv6Header);
3138 switch (pkt6->next_header)
3139 {
3140 case IPPROTO_UDP:
3141 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt6[1], size,
3142 AF_INET6,
3143 &pkt6->destination_address,
3144 &pkt6->source_address);
3145 break;
3146
3147 case IPPROTO_TCP:
3148 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt6[1], size,
3149 AF_INET6,
3150 &pkt6->destination_address,
3151 &pkt6->source_address);
3152 break;
3153
3154 case IPPROTO_ICMPV6:
3155 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt6[1], size,
3156 AF_INET6,
3157 &pkt6->destination_address,
3158 &pkt6->source_address);
3159 break;
3160
3161 default:
3162 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3163 _ (
3164 "IPv6 packet with unsupported next header %d received. Ignored.\n"),
3165 pkt6->next_header);
3166 return GNUNET_OK;
3167 }
3168 }
3169 break;
3170
3171 default:
3172 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3173 _ ("Packet from unknown protocol %u received. Ignored.\n"),
3174 ntohs (pkt_tun->proto));
3175 break;
3176 }
3177 return GNUNET_OK;
3178}
3179
3180
3181/**
3182 * Callback from CADET for new channels.
3183 *
3184 * @param cls closure
3185 * @param channel new handle to the channel
3186 * @param initiator peer that started the channel
3187 * @return initial channel context for the channel
3188 */
3189static void *
3190new_channel (void *cls,
3191 struct GNUNET_CADET_Channel *channel,
3192 const struct GNUNET_PeerIdentity *initiator)
3193{
3194 struct ChannelState *s = GNUNET_new (struct ChannelState);
3195
3196 s->is_dns = GNUNET_SYSERR;
3197 s->peer = *initiator;
3198 GNUNET_STATISTICS_update (stats,
3199 gettext_noop ("# Inbound CADET channels created"),
3200 1,
3201 GNUNET_NO);
3202 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3203 "Received inbound channel from `%s'\n",
3204 GNUNET_i2s (initiator));
3205 s->channel = channel;
3206 return s;
3207}
3208
3209
3210/**
3211 * Function that frees everything from a hashmap
3212 *
3213 * @param cls unused
3214 * @param hash key
3215 * @param value value to free
3216 */
3217static int
3218free_iterate (void *cls,
3219 const struct GNUNET_HashCode *hash,
3220 void *value)
3221{
3222 GNUNET_free (value);
3223 return GNUNET_YES;
3224}
3225
3226
3227/**
3228 * Function scheduled as very last function if the service
3229 * disabled itself because the helper is not installed
3230 * properly. Does nothing, except for keeping the
3231 * service process alive by virtue of being scheduled.
3232 *
3233 * @param cls NULL
3234 * @param tc scheduler context
3235 */
3236static void
3237dummy_task (void *cls)
3238{
3239 /* just terminate */
3240}
3241
3242
3243/**
3244 * Function scheduled as very last function, cleans up after us
3245 *
3246 * @param cls NULL
3247 */
3248static void
3249cleanup (void *cls)
3250{
3251 unsigned int i;
3252
3253 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3254 "Exit service is shutting down now\n");
3255
3256 if (NULL != helper_handle)
3257 {
3258 GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
3259 helper_handle = NULL;
3260 }
3261 if (NULL != regex4)
3262 {
3263 GNUNET_REGEX_announce_cancel (regex4);
3264 regex4 = NULL;
3265 }
3266 if (NULL != regex6)
3267 {
3268 GNUNET_REGEX_announce_cancel (regex6);
3269 regex6 = NULL;
3270 }
3271 if (NULL != services)
3272 {
3273 GNUNET_CONTAINER_multihashmap_iterate (services,
3274 &free_service_record,
3275 NULL);
3276 GNUNET_CONTAINER_multihashmap_destroy (services);
3277 }
3278 if (NULL != dns_port)
3279 {
3280 GNUNET_CADET_close_port (dns_port);
3281 dns_port = NULL;
3282 }
3283 if (NULL != cadet_port4)
3284 {
3285 GNUNET_CADET_close_port (cadet_port4);
3286 cadet_port4 = NULL;
3287 }
3288 if (NULL != cadet_port6)
3289 {
3290 GNUNET_CADET_close_port (cadet_port6);
3291 cadet_port6 = NULL;
3292 }
3293 if (NULL != cadet_handle)
3294 {
3295 GNUNET_CADET_disconnect (cadet_handle);
3296 cadet_handle = NULL;
3297 }
3298 if (NULL != connections_map)
3299 {
3300 GNUNET_CONTAINER_multihashmap_iterate (connections_map,
3301 &free_iterate,
3302 NULL);
3303 GNUNET_CONTAINER_multihashmap_destroy (connections_map);
3304 connections_map = NULL;
3305 }
3306 if (NULL != connections_heap)
3307 {
3308 GNUNET_CONTAINER_heap_destroy (connections_heap);
3309 connections_heap = NULL;
3310 }
3311 if (NULL != dnsstub)
3312 {
3313 GNUNET_DNSSTUB_stop (dnsstub);
3314 dnsstub = NULL;
3315 }
3316 if (NULL != peer_key)
3317 {
3318 GNUNET_free (peer_key);
3319 peer_key = NULL;
3320 }
3321 if (NULL != dht_task)
3322 {
3323 GNUNET_SCHEDULER_cancel (dht_task);
3324 dht_task = NULL;
3325 }
3326 if (NULL != dht_put)
3327 {
3328 GNUNET_DHT_put_cancel (dht_put);
3329 dht_put = NULL;
3330 }
3331 if (NULL != dht)
3332 {
3333 GNUNET_DHT_disconnect (dht);
3334 dht = NULL;
3335 }
3336 if (NULL != stats)
3337 {
3338 GNUNET_STATISTICS_destroy (stats,
3339 GNUNET_NO);
3340 stats = NULL;
3341 }
3342 for (i = 0; i < 8; i++)
3343 GNUNET_free (exit_argv[i]);
3344}
3345
3346
3347/**
3348 * Add services to the service map.
3349 *
3350 * @param proto IPPROTO_TCP or IPPROTO_UDP
3351 * @param cpy copy of the service descriptor (can be mutilated)
3352 * @param name DNS name of the service
3353 */
3354static void
3355add_services (int proto,
3356 char *cpy,
3357 const char *name)
3358{
3359 char *redirect;
3360 char *hostname;
3361 char *hostport;
3362 struct LocalService *serv;
3363 char *n;
3364 size_t slen;
3365
3366 slen = strlen (name);
3367 GNUNET_assert (slen >= 8);
3368 n = GNUNET_strndup (name, slen - 8 /* remove .gnunet. */);
3369
3370 for (redirect = strtok (cpy, " ;"); redirect != NULL;
3371 redirect = strtok (NULL, " ;"))
3372 {
3373 if (NULL == (hostname = strstr (redirect, ":")))
3374 {
3375 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3376 _ (
3377 "Option `%s' for domain `%s' is not formatted correctly!\n"),
3378 redirect,
3379 name);
3380 continue;
3381 }
3382 hostname[0] = '\0';
3383 hostname++;
3384 if (NULL == (hostport = strstr (hostname, ":")))
3385 {
3386 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3387 _ (
3388 "Option `%s' for domain `%s' is not formatted correctly!\n"),
3389 redirect,
3390 name);
3391 continue;
3392 }
3393 hostport[0] = '\0';
3394 hostport++;
3395
3396 int local_port = atoi (redirect);
3397 int remote_port = atoi (hostport);
3398
3399 if (! ((local_port > 0) && (local_port < 65536)))
3400 {
3401 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3402 _ ("`%s' is not a valid port number (for domain `%s')!"),
3403 redirect,
3404 name);
3405 continue;
3406 }
3407 if (! ((remote_port > 0) && (remote_port < 65536)))
3408 {
3409 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3410 _ ("`%s' is not a valid port number (for domain `%s')!"),
3411 hostport,
3412 name);
3413 continue;
3414 }
3415
3416 serv = GNUNET_new (struct LocalService);
3417 serv->address.proto = proto;
3418 serv->address.port = remote_port;
3419 if (0 == strcmp ("localhost4",
3420 hostname))
3421 {
3422 const char *ip4addr = exit_argv[5];
3423
3424 serv->address.af = AF_INET;
3425 GNUNET_assert (1 == inet_pton (AF_INET,
3426 ip4addr,
3427 &serv->address.address.ipv4));
3428 }
3429 else if (0 == strcmp ("localhost6",
3430 hostname))
3431 {
3432 const char *ip6addr = exit_argv[3];
3433
3434 serv->address.af = AF_INET6;
3435 GNUNET_assert (1 == inet_pton (AF_INET6,
3436 ip6addr,
3437 &serv->address.address.ipv6));
3438 }
3439 else
3440 {
3441 struct addrinfo *res;
3442 int ret;
3443
3444 ret = getaddrinfo (hostname,
3445 NULL,
3446 NULL,
3447 &res);
3448 if ((0 != ret) || (NULL == res))
3449 {
3450 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3451 _ (
3452 "No addresses found for hostname `%s' of service `%s'!\n"),
3453 hostname,
3454 n);
3455 GNUNET_free (serv);
3456 continue;
3457 }
3458
3459 serv->address.af = res->ai_family;
3460 switch (res->ai_family)
3461 {
3462 case AF_INET:
3463 if (! ipv4_enabled)
3464 {
3465 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3466 _ (
3467 "Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
3468 n);
3469 freeaddrinfo (res);
3470 GNUNET_free (serv);
3471 continue;
3472 }
3473 serv->address.address.ipv4
3474 = ((struct sockaddr_in *) res->ai_addr)->sin_addr;
3475 break;
3476
3477 case AF_INET6:
3478 if (! ipv6_enabled)
3479 {
3480 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3481 _ (
3482 "Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
3483 n);
3484 freeaddrinfo (res);
3485 GNUNET_free (serv);
3486 continue;
3487 }
3488 serv->address.address.ipv6
3489 = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
3490 break;
3491
3492 default:
3493 freeaddrinfo (res);
3494 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3495 _ (
3496 "No IP addresses found for hostname `%s' of service `%s'!\n"),
3497 hostname,
3498 n);
3499 GNUNET_free (serv);
3500 continue;
3501 }
3502 freeaddrinfo (res);
3503 }
3504 store_service (proto,
3505 n,
3506 local_port,
3507 serv);
3508 }
3509 GNUNET_free (n);
3510}
3511
3512
3513/**
3514 * Reads the configuration and populates #udp_services and #tcp_services
3515 *
3516 * @param cls unused
3517 * @param section name of section in config
3518 */
3519static void
3520read_service_conf (void *cls,
3521 const char *section)
3522{
3523 char *cpy;
3524
3525 if ((strlen (section) < 8) ||
3526 (0 != strcmp (".gnunet.", section + (strlen (section) - 8))))
3527 return;
3528 if (GNUNET_OK ==
3529 GNUNET_CONFIGURATION_get_value_string (cfg,
3530 section,
3531 "UDP_REDIRECTS",
3532 &cpy))
3533 {
3534 add_services (IPPROTO_UDP,
3535 cpy,
3536 section);
3537 GNUNET_free (cpy);
3538 }
3539 if (GNUNET_OK ==
3540 GNUNET_CONFIGURATION_get_value_string (cfg,
3541 section,
3542 "TCP_REDIRECTS",
3543 &cpy))
3544 {
3545 add_services (IPPROTO_TCP,
3546 cpy,
3547 section);
3548 GNUNET_free (cpy);
3549 }
3550}
3551
3552
3553/**
3554 * We are running a DNS exit service, advertise it in the
3555 * DHT. This task is run periodically to do the DHT PUT.
3556 *
3557 * @param cls closure
3558 */
3559static void
3560do_dht_put (void *cls);
3561
3562
3563/**
3564 * Function called when the DHT PUT operation is complete.
3565 * Schedules the next PUT.
3566 *
3567 * @param cls closure, NULL
3568 */
3569static void
3570dht_put_cont (void *cls)
3571{
3572 dht_put = NULL;
3573}
3574
3575
3576/**
3577 * We are running a DNS exit service, advertise it in the
3578 * DHT. This task is run periodically to do the DHT PUT.
3579 *
3580 * @param cls closure
3581 */
3582static void
3583do_dht_put (void *cls)
3584{
3585 struct GNUNET_TIME_Absolute expiration;
3586
3587 dht_task = GNUNET_SCHEDULER_add_delayed (DHT_PUT_FREQUENCY,
3588 &do_dht_put,
3589 NULL);
3590 expiration = GNUNET_TIME_absolute_ntoh (dns_advertisement.expiration_time);
3591 if (GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us <
3592 GNUNET_TIME_UNIT_HOURS.rel_value_us)
3593 {
3594 /* refresh advertisement */
3595 expiration = GNUNET_TIME_relative_to_absolute (DNS_ADVERTISEMENT_TIMEOUT);
3596 dns_advertisement.expiration_time = GNUNET_TIME_absolute_hton (expiration);
3597 GNUNET_assert (GNUNET_OK ==
3598 GNUNET_CRYPTO_eddsa_sign_ (peer_key,
3599 &dns_advertisement.purpose,
3600 &dns_advertisement.signature));
3601 }
3602 if (NULL != dht_put)
3603 GNUNET_DHT_put_cancel (dht_put);
3604 dht_put = GNUNET_DHT_put (dht,
3605 &dht_put_key,
3606 1 /* replication */,
3607 GNUNET_DHT_RO_NONE,
3608 GNUNET_BLOCK_TYPE_DNS,
3609 sizeof(struct GNUNET_DNS_Advertisement),
3610 &dns_advertisement,
3611 expiration,
3612 &dht_put_cont,
3613 NULL);
3614}
3615
3616
3617/**
3618 * Figure out which IP versions we should support (and which
3619 * are supported by the OS) according to our configuration.
3620 */
3621static void
3622parse_ip_options ()
3623{
3624 ipv4_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg,
3625 "exit",
3626 "EXIT_IPV4");
3627 ipv6_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg,
3628 "exit",
3629 "EXIT_IPV6");
3630 ipv4_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg,
3631 "exit",
3632 "ENABLE_IPV4");
3633 ipv6_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg,
3634 "exit",
3635 "ENABLE_IPV6");
3636 if ((ipv4_exit || ipv4_enabled) &&
3637 (GNUNET_OK != GNUNET_NETWORK_test_pf (PF_INET)) )
3638 {
3639 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3640 _ (
3641 "This system does not support IPv4, will disable IPv4 functions despite them being enabled in the configuration\n"));
3642 ipv4_exit = GNUNET_NO;
3643 ipv4_enabled = GNUNET_NO;
3644 }
3645 if ((ipv6_exit || ipv6_enabled) &&
3646 (GNUNET_OK != GNUNET_NETWORK_test_pf (PF_INET6)) )
3647 {
3648 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3649 _ (
3650 "This system does not support IPv6, will disable IPv6 functions despite them being enabled in the configuration\n"));
3651 ipv6_exit = GNUNET_NO;
3652 ipv6_enabled = GNUNET_NO;
3653 }
3654 if (ipv4_exit && (! ipv4_enabled))
3655 {
3656 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3657 _ (
3658 "Cannot enable IPv4 exit but disable IPv4 on TUN interface, will use ENABLE_IPv4=YES\n"));
3659 ipv4_enabled = GNUNET_YES;
3660 }
3661 if (ipv6_exit && (! ipv6_enabled))
3662 {
3663 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3664 _ (
3665 "Cannot enable IPv6 exit but disable IPv6 on TUN interface, will use ENABLE_IPv6=YES\n"));
3666 ipv6_enabled = GNUNET_YES;
3667 }
3668}
3669
3670
3671/**
3672 * Helper function to open the CADET port for DNS exits and to
3673 * advertise the DNS exit (if applicable).
3674 */
3675static void
3676advertise_dns_exit ()
3677{
3678 struct GNUNET_MQ_MessageHandler handlers[] = {
3679 GNUNET_MQ_hd_var_size (dns_request,
3680 GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET,
3681 struct DnsResponseMessage,
3682 NULL),
3683 GNUNET_MQ_handler_end ()
3684 };
3685 char *dns_exit;
3686 struct GNUNET_HashCode port;
3687
3688 if (GNUNET_YES !=
3689 GNUNET_CONFIGURATION_get_value_yesno (cfg,
3690 "exit",
3691 "EXIT_DNS"))
3692 return;
3693 GNUNET_assert (NULL != (dnsstub = GNUNET_DNSSTUB_start (128)));
3694 dns_exit = NULL;
3695 /* TODO: support using multiple DNS resolvers */
3696 if ((GNUNET_OK !=
3697 GNUNET_CONFIGURATION_get_value_string (cfg,
3698 "exit",
3699 "DNS_RESOLVER",
3700 &dns_exit)) ||
3701 (GNUNET_OK !=
3702 GNUNET_DNSSTUB_add_dns_ip (dnsstub,
3703 dns_exit)))
3704 {
3705 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
3706 "dns",
3707 "DNS_RESOLVER",
3708 _ ("need a valid IPv4 or IPv6 address\n"));
3709 GNUNET_free (dns_exit);
3710 return;
3711 }
3712 /* open port */
3713 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_INTERNET_RESOLVER,
3714 strlen (GNUNET_APPLICATION_PORT_INTERNET_RESOLVER),
3715 &port);
3716 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3717 "Opening CADET port %s for DNS exit service\n",
3718 GNUNET_h2s (&port));
3719 dns_port = GNUNET_CADET_open_port (cadet_handle,
3720 &port,
3721 &new_channel,
3722 NULL,
3723 NULL,
3724 &clean_channel,
3725 handlers);
3726 /* advertise exit */
3727 dht = GNUNET_DHT_connect (cfg,
3728 1);
3729 peer_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
3730 GNUNET_CRYPTO_eddsa_key_get_public (peer_key,
3731 &dns_advertisement.peer.public_key);
3732 dns_advertisement.purpose.size = htonl (sizeof(struct
3733 GNUNET_DNS_Advertisement)
3734 - sizeof(struct
3735 GNUNET_CRYPTO_EddsaSignature));
3736 dns_advertisement.purpose.purpose = htonl (
3737 GNUNET_SIGNATURE_PURPOSE_DNS_RECORD);
3738 GNUNET_CRYPTO_hash ("dns",
3739 strlen ("dns"),
3740 &dht_put_key);
3741 dht_task = GNUNET_SCHEDULER_add_now (&do_dht_put,
3742 NULL);
3743 GNUNET_free (dns_exit);
3744}
3745
3746
3747/**
3748 * Initialize #exit_argv.
3749 *
3750 * @return #GNUNET_OK on success, #GNUNET_SYSERR if we should shutdown
3751 */
3752static int
3753setup_exit_helper_args ()
3754{
3755 char *exit_ifname;
3756 char *tun_ifname;
3757 char *ipv6addr;
3758 char *ipv6prefix_s;
3759 char *ipv4addr;
3760 char *ipv4mask;
3761
3762 exit_argv[0] = GNUNET_strdup ("exit-gnunet");
3763 if (GNUNET_SYSERR ==
3764 GNUNET_CONFIGURATION_get_value_string (cfg,
3765 "exit",
3766 "TUN_IFNAME",
3767 &tun_ifname))
3768 {
3769 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3770 "EXIT",
3771 "TUN_IFNAME");
3772 return GNUNET_SYSERR;
3773 }
3774 exit_argv[1] = tun_ifname;
3775 if (ipv4_enabled)
3776 {
3777 if (GNUNET_SYSERR ==
3778 GNUNET_CONFIGURATION_get_value_string (cfg,
3779 "exit",
3780 "EXIT_IFNAME",
3781 &exit_ifname))
3782 {
3783 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3784 "EXIT",
3785 "EXIT_IFNAME");
3786 return GNUNET_SYSERR;
3787 }
3788 exit_argv[2] = exit_ifname;
3789 }
3790 else
3791 {
3792 exit_argv[2] = GNUNET_strdup ("-");
3793 }
3794
3795 if (GNUNET_YES == ipv6_enabled)
3796 {
3797 ipv6addr = NULL;
3798 if (((GNUNET_SYSERR ==
3799 GNUNET_CONFIGURATION_get_value_string (cfg,
3800 "exit",
3801 "IPV6ADDR",
3802 &ipv6addr)) ||
3803 (1 != inet_pton (AF_INET6,
3804 ipv6addr,
3805 &exit_ipv6addr))))
3806 {
3807 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3808 "EXIT",
3809 "IPV6ADDR");
3810 GNUNET_free (ipv6addr);
3811 return GNUNET_SYSERR;
3812 }
3813 exit_argv[3] = ipv6addr;
3814 if (GNUNET_SYSERR ==
3815 GNUNET_CONFIGURATION_get_value_string (cfg,
3816 "exit",
3817 "IPV6PREFIX",
3818 &ipv6prefix_s))
3819 {
3820 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3821 "EXIT",
3822 "IPV6PREFIX");
3823 return GNUNET_SYSERR;
3824 }
3825 exit_argv[4] = ipv6prefix_s;
3826 if ((GNUNET_OK !=
3827 GNUNET_CONFIGURATION_get_value_number (cfg,
3828 "exit",
3829 "IPV6PREFIX",
3830 &ipv6prefix)) ||
3831 (ipv6prefix >= 127))
3832 {
3833 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
3834 "EXIT",
3835 "IPV6PREFIX",
3836 _ ("Must be a number"));
3837 return GNUNET_SYSERR;
3838 }
3839 }
3840 else
3841 {
3842 /* IPv6 explicitly disabled */
3843 exit_argv[3] = GNUNET_strdup ("-");
3844 exit_argv[4] = GNUNET_strdup ("-");
3845 }
3846 if (GNUNET_YES == ipv4_enabled)
3847 {
3848 ipv4addr = NULL;
3849 if (((GNUNET_SYSERR ==
3850 GNUNET_CONFIGURATION_get_value_string (cfg,
3851 "exit",
3852 "IPV4ADDR",
3853 &ipv4addr)) ||
3854 (1 != inet_pton (AF_INET,
3855 ipv4addr,
3856 &exit_ipv4addr))))
3857 {
3858 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3859 "EXIT",
3860 "IPV4ADDR");
3861 GNUNET_free (ipv4addr);
3862 return GNUNET_SYSERR;
3863 }
3864 exit_argv[5] = ipv4addr;
3865 ipv4mask = NULL;
3866 if (((GNUNET_SYSERR ==
3867 GNUNET_CONFIGURATION_get_value_string (cfg,
3868 "exit",
3869 "IPV4MASK",
3870 &ipv4mask)) ||
3871 (1 != inet_pton (AF_INET,
3872 ipv4mask,
3873 &exit_ipv4mask))))
3874 {
3875 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3876 "EXIT",
3877 "IPV4MASK");
3878 GNUNET_free (ipv4mask);
3879 return GNUNET_SYSERR;
3880 }
3881 exit_argv[6] = ipv4mask;
3882 }
3883 else
3884 {
3885 /* IPv4 explicitly disabled */
3886 exit_argv[5] = GNUNET_strdup ("-");
3887 exit_argv[6] = GNUNET_strdup ("-");
3888 }
3889 exit_argv[7] = NULL;
3890 return GNUNET_OK;
3891}
3892
3893
3894/**
3895 * @brief Main function that will be run by the scheduler.
3896 *
3897 * @param cls closure
3898 * @param args remaining command-line arguments
3899 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
3900 * @param cfg_ configuration
3901 */
3902static void
3903run (void *cls,
3904 char *const *args,
3905 const char *cfgfile,
3906 const struct GNUNET_CONFIGURATION_Handle *cfg_)
3907{
3908 struct GNUNET_MQ_MessageHandler handlers[] = {
3909 GNUNET_MQ_hd_var_size (icmp_remote,
3910 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET,
3911 struct GNUNET_EXIT_IcmpInternetMessage,
3912 NULL),
3913 GNUNET_MQ_hd_var_size (udp_remote,
3914 GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET,
3915 struct GNUNET_EXIT_UdpInternetMessage,
3916 NULL),
3917 GNUNET_MQ_hd_var_size (tcp_remote,
3918 GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START,
3919 struct GNUNET_EXIT_TcpInternetStartMessage,
3920 NULL),
3921 GNUNET_MQ_hd_var_size (tcp_data,
3922 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT,
3923 struct GNUNET_EXIT_TcpDataMessage,
3924 NULL),
3925 GNUNET_MQ_handler_end ()
3926 };
3927 struct GNUNET_HashCode port;
3928 char *policy;
3929 char *binary;
3930 char *regex;
3931 char *prefixed_regex;
3932
3933 cfg = cfg_;
3934 if (GNUNET_OK !=
3935 GNUNET_CONFIGURATION_get_value_number (cfg,
3936 "exit",
3937 "MAX_CONNECTIONS",
3938 &max_connections))
3939 max_connections = 1024;
3940 parse_ip_options ();
3941 binary = GNUNET_OS_get_suid_binary_path (cfg, "gnunet-helper-exit");
3942 if ((ipv4_exit) || (ipv6_exit))
3943 {
3944 if (GNUNET_YES !=
3945 GNUNET_OS_check_helper_binary (binary,
3946 GNUNET_YES,
3947 "gnunet-vpn - - - 169.1.3.7 255.255.255.0")) // no nat, ipv4 only
3948 {
3949 GNUNET_free (binary);
3950 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3951 _ (
3952 "`%s' is not SUID or the path is invalid, EXIT will not work\n"),
3953 "gnunet-helper-exit");
3954 GNUNET_SCHEDULER_add_shutdown (&dummy_task,
3955 NULL);
3956 global_ret = 1;
3957 return;
3958 }
3959 }
3960 if (! (ipv4_enabled || ipv6_enabled))
3961 {
3962 GNUNET_free (binary);
3963 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3964 _ ("No useful service enabled. Exiting.\n"));
3965 GNUNET_SCHEDULER_shutdown ();
3966 return;
3967 }
3968
3969 GNUNET_SCHEDULER_add_shutdown (&cleanup,
3970 NULL);
3971 stats = GNUNET_STATISTICS_create ("exit",
3972 cfg);
3973 cadet_handle = GNUNET_CADET_connect (cfg);
3974 if (NULL == cadet_handle)
3975 {
3976 GNUNET_free (binary);
3977 GNUNET_SCHEDULER_shutdown ();
3978 return;
3979 }
3980 advertise_dns_exit ();
3981 if (GNUNET_OK !=
3982 setup_exit_helper_args ())
3983 {
3984 GNUNET_free (binary);
3985 GNUNET_SCHEDULER_shutdown ();
3986 return;
3987 }
3988
3989 services = GNUNET_CONTAINER_multihashmap_create (65536,
3990 GNUNET_NO);
3991 connections_map = GNUNET_CONTAINER_multihashmap_create (65536,
3992 GNUNET_NO);
3993 connections_heap = GNUNET_CONTAINER_heap_create (
3994 GNUNET_CONTAINER_HEAP_ORDER_MIN);
3995 GNUNET_CONFIGURATION_iterate_sections (cfg,
3996 &read_service_conf,
3997 NULL);
3998
3999 /* Cadet handle acquired, now open ports and announce regular
4000 expressions matching our exit */
4001 if ((GNUNET_YES == ipv4_enabled) &&
4002 (GNUNET_YES == ipv4_exit))
4003 {
4004 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_IPV4_GATEWAY,
4005 strlen (GNUNET_APPLICATION_PORT_IPV4_GATEWAY),
4006 &port);
4007 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4008 "Opening CADET port %s for IPv4 gateway service\n",
4009 GNUNET_h2s (&port));
4010 cadet_port4 = GNUNET_CADET_open_port (cadet_handle,
4011 &port,
4012 &new_channel,
4013 NULL,
4014 NULL,
4015 &clean_channel,
4016 handlers);
4017 policy = NULL;
4018 if (GNUNET_OK !=
4019 GNUNET_CONFIGURATION_get_value_string (cfg,
4020 "exit",
4021 "EXIT_RANGE_IPV4_POLICY",
4022 &policy))
4023 regex = NULL;
4024 else
4025 regex = GNUNET_TUN_ipv4policy2regex (policy);
4026 GNUNET_free (policy);
4027 if (NULL != regex)
4028 {
4029 (void) GNUNET_asprintf (&prefixed_regex,
4030 "%s%s",
4031 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
4032 regex);
4033 regex4 = GNUNET_REGEX_announce (cfg,
4034 prefixed_regex,
4035 REGEX_REFRESH_FREQUENCY,
4036 REGEX_MAX_PATH_LEN_IPV4);
4037 GNUNET_free (regex);
4038 GNUNET_free (prefixed_regex);
4039 }
4040 }
4041
4042 if ((GNUNET_YES == ipv6_enabled) && (GNUNET_YES == ipv6_exit))
4043 {
4044 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_IPV6_GATEWAY,
4045 strlen (GNUNET_APPLICATION_PORT_IPV6_GATEWAY),
4046 &port);
4047 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4048 "Opening CADET port %s for IPv6 gateway service\n",
4049 GNUNET_h2s (&port));
4050 cadet_port6 = GNUNET_CADET_open_port (cadet_handle,
4051 &port,
4052 &new_channel,
4053 NULL,
4054 NULL,
4055 &clean_channel,
4056 handlers);
4057 policy = NULL;
4058 if (GNUNET_OK !=
4059 GNUNET_CONFIGURATION_get_value_string (cfg,
4060 "exit",
4061 "EXIT_RANGE_IPV6_POLICY",
4062 &policy))
4063 regex = NULL;
4064 else
4065 regex = GNUNET_TUN_ipv6policy2regex (policy);
4066 GNUNET_free (policy);
4067 if (NULL != regex)
4068 {
4069 (void) GNUNET_asprintf (&prefixed_regex,
4070 "%s%s",
4071 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
4072 regex);
4073 regex6 = GNUNET_REGEX_announce (cfg,
4074 prefixed_regex,
4075 REGEX_REFRESH_FREQUENCY,
4076 REGEX_MAX_PATH_LEN_IPV6);
4077 GNUNET_free (regex);
4078 GNUNET_free (prefixed_regex);
4079 }
4080 }
4081 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
4082 binary,
4083 exit_argv,
4084 &message_token,
4085 NULL,
4086 NULL);
4087 GNUNET_free (binary);
4088}
4089
4090
4091/**
4092 * The main function
4093 *
4094 * @param argc number of arguments from the command line
4095 * @param argv command line arguments
4096 * @return 0 ok, 1 on error
4097 */
4098int
4099main (int argc,
4100 char *const *argv)
4101{
4102 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
4103 GNUNET_GETOPT_OPTION_END
4104 };
4105
4106 if (GNUNET_OK !=
4107 GNUNET_STRINGS_get_utf8_args (argc,
4108 argv,
4109 &argc,
4110 &argv))
4111 return 2;
4112
4113 return (GNUNET_OK ==
4114 GNUNET_PROGRAM_run (argc,
4115 argv,
4116 "gnunet-daemon-exit",
4117 gettext_noop (
4118 "Daemon to run to provide an IP exit node for the VPN"),
4119 options,
4120 &run,
4121 NULL)) ? global_ret : 1;
4122}
4123
4124
4125/* end of gnunet-daemon-exit.c */
diff --git a/src/exit/gnunet-helper-exit.c b/src/exit/gnunet-helper-exit.c
deleted file mode 100644
index 4f32ea1f1..000000000
--- a/src/exit/gnunet-helper-exit.c
+++ /dev/null
@@ -1,859 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010, 2011, 2012 Christian Grothoff
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file exit/gnunet-helper-exit.c
23 *
24 * @brief the helper for exit nodes. Opens a virtual
25 * network-interface, sends data received on the if to stdout, sends
26 * data received on stdin to the interface. The code also enables
27 * IPv4/IPv6 forwarding and NAT on the current system (the latter on
28 * an interface specified on the command-line); these changes to the
29 * network configuration are NOT automatically undone when the program
30 * is stopped (this is because we cannot be sure that some other
31 * application didn't enable them before or after us; also, these
32 * changes should be mostly harmless as it simply turns the system
33 * into a router).
34 *
35 * @author Philipp Tölke
36 * @author Christian Grothoff
37 *
38 * The following list of people have reviewed this code and considered
39 * it safe since the last modification (if you reviewed it, please
40 * have your name added to the list):
41 *
42 * - Philipp Tölke
43 */
44#include "platform.h"
45
46#ifdef IF_TUN_HDR
47#include IF_TUN_HDR
48#endif
49
50#if defined(BSD) || defined(SOLARIS)
51#define ifr_netmask ifr_ifru.ifru_addr
52#define SIOGIFINDEX SIOCGIFINDEX
53#endif
54
55/**
56 * Need 'struct GNUNET_MessageHeader'.
57 */
58#include "gnunet_crypto_lib.h"
59#include "gnunet_common.h"
60
61/**
62 * Need VPN message types.
63 */
64#include "gnunet_protocols.h"
65
66/**
67 * Should we print (interesting|debug) messages that can happen during
68 * normal operation?
69 */
70#define DEBUG GNUNET_NO
71
72/**
73 * Maximum size of a GNUnet message (GNUNET_MAX_MESSAGE_SIZE)
74 */
75#define MAX_SIZE 65536
76
77/**
78 * Path to 'sysctl' binary.
79 */
80static const char *sbin_sysctl;
81
82/**
83 * Path to 'iptables' binary.
84 */
85static const char *sbin_iptables;
86
87
88#if ! defined(__ANDROID__)
89#if ! defined(_LINUX_IN6_H) && defined(__linux__)
90/**
91 * This is in linux/include/net/ipv6.h, but not always exported.
92 */
93struct in6_ifreq
94{
95 struct in6_addr ifr6_addr;
96 uint32_t ifr6_prefixlen; /* __u32 in the original */
97 int ifr6_ifindex;
98};
99#endif
100#endif
101
102
103/**
104 * Open '/dev/null' and make the result the given
105 * file descriptor.
106 *
107 * @param target_fd desired FD to point to /dev/null
108 * @param flags open flags (O_RDONLY, O_WRONLY)
109 */
110static void
111open_dev_null (int target_fd,
112 int flags)
113{
114 int fd;
115
116 fd = open ("/dev/null", flags);
117 if (-1 == fd)
118 abort ();
119 if (fd == target_fd)
120 return;
121 if (-1 == dup2 (fd, target_fd))
122 {
123 (void) close (fd);
124 abort ();
125 }
126 (void) close (fd);
127}
128
129
130/**
131 * Run the given command and wait for it to complete.
132 *
133 * @param file name of the binary to run
134 * @param cmd command line arguments (as given to 'execv')
135 * @return 0 on success, 1 on any error
136 */
137static int
138fork_and_exec (const char *file,
139 char *const cmd[])
140{
141 int status;
142 pid_t pid;
143 pid_t ret;
144
145 pid = fork ();
146 if (-1 == pid)
147 {
148 fprintf (stderr,
149 "fork failed: %s\n",
150 strerror (errno));
151 return 1;
152 }
153 if (0 == pid)
154 {
155 /* we are the child process */
156 /* close stdin/stdout to not cause interference
157 with the helper's main protocol! */
158 (void) close (0);
159 open_dev_null (0, O_RDONLY);
160 (void) close (1);
161 open_dev_null (1, O_WRONLY);
162 (void) execv (file, cmd);
163 /* can only get here on error */
164 fprintf (stderr,
165 "exec `%s' failed: %s\n",
166 file,
167 strerror (errno));
168 _exit (1);
169 }
170 /* keep running waitpid as long as the only error we get is 'EINTR' */
171 while ((-1 == (ret = waitpid (pid, &status, 0))) &&
172 (errno == EINTR))
173 ;
174 if (-1 == ret)
175 {
176 fprintf (stderr,
177 "waitpid failed: %s\n",
178 strerror (errno));
179 return 1;
180 }
181 if (! (WIFEXITED (status) && (0 == WEXITSTATUS (status))))
182 return 1;
183 /* child process completed and returned success, we're happy */
184 return 0;
185}
186
187
188/**
189 * Creates a tun-interface called dev;
190 *
191 * @param dev is assumed to point to a char[IFNAMSIZ]
192 * if *dev == '\\0', uses the name supplied by the kernel;
193 * @return the fd to the tun or -1 on error
194 */
195#ifdef IFF_TUN /* LINUX */
196static int
197init_tun (char *dev)
198{
199 struct ifreq ifr;
200 int fd;
201
202 if (NULL == dev)
203 {
204 errno = EINVAL;
205 return -1;
206 }
207
208 if (-1 == (fd = open ("/dev/net/tun", O_RDWR)))
209 {
210 fprintf (stderr, "Error opening `%s': %s\n", "/dev/net/tun",
211 strerror (errno));
212 return -1;
213 }
214
215 if (fd >= FD_SETSIZE)
216 {
217 fprintf (stderr, "File descriptor to large: %d", fd);
218 (void) close (fd);
219 return -1;
220 }
221
222 memset (&ifr, 0, sizeof(ifr));
223 ifr.ifr_flags = IFF_TUN;
224
225 if ('\0' != *dev)
226 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
227
228 if (-1 == ioctl (fd, TUNSETIFF, (void *) &ifr))
229 {
230 fprintf (stderr,
231 "Error with ioctl on `%s': %s\n", "/dev/net/tun",
232 strerror (errno));
233 (void) close (fd);
234 return -1;
235 }
236 strcpy (dev, ifr.ifr_name);
237 return fd;
238}
239
240
241#else /* BSD et al, including DARWIN */
242
243#ifdef SIOCIFCREATE
244static int
245init_tun (char *dev)
246{
247 int fd;
248 int s;
249 struct ifreq ifr;
250
251 fd = open (dev, O_RDWR);
252 if (fd == -1)
253 {
254 s = socket (AF_INET, SOCK_DGRAM, 0);
255 if (s < 0)
256 return -1;
257 memset (&ifr, 0, sizeof(ifr));
258 strncpy (ifr.ifr_name, dev + 5, sizeof(ifr.ifr_name) - 1);
259 if (! ioctl (s, SIOCIFCREATE, &ifr))
260 fd = open (dev, O_RDWR);
261 close (s);
262 }
263 return fd;
264}
265
266
267#else
268#define init_tun(dev) open (dev, O_RDWR)
269#endif
270#endif /* !IFF_TUN (BSD) */
271
272/**
273 * @brief Sets the IPv6-Address given in address on the interface dev
274 *
275 * @param dev the interface to configure
276 * @param address the IPv6-Address
277 * @param prefix_len the length of the network-prefix
278 */
279static void
280set_address6 (const char *dev, const char *address, unsigned long prefix_len)
281{
282 struct ifreq ifr;
283 struct sockaddr_in6 sa6;
284 int fd;
285 struct in6_ifreq ifr6;
286
287 /*
288 * parse the new address
289 */
290 memset (&sa6, 0, sizeof(struct sockaddr_in6));
291 sa6.sin6_family = AF_INET6;
292 if (1 != inet_pton (AF_INET6, address, &sa6.sin6_addr))
293 {
294 fprintf (stderr, "Failed to parse address `%s': %s\n", address,
295 strerror (errno));
296 exit (1);
297 }
298
299 if (-1 == (fd = socket (PF_INET6, SOCK_DGRAM, 0)))
300 {
301 fprintf (stderr, "Error creating socket: %s\n", strerror (errno));
302 exit (1);
303 }
304
305 memset (&ifr, 0, sizeof(struct ifreq));
306 /*
307 * Get the index of the if
308 */
309 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
310 if (-1 == ioctl (fd, SIOGIFINDEX, &ifr))
311 {
312 fprintf (stderr, "ioctl failed at %d: %s\n", __LINE__, strerror (errno));
313 (void) close (fd);
314 exit (1);
315 }
316
317 memset (&ifr6, 0, sizeof(struct in6_ifreq));
318 ifr6.ifr6_addr = sa6.sin6_addr;
319 ifr6.ifr6_ifindex = ifr.ifr_ifindex;
320 ifr6.ifr6_prefixlen = prefix_len;
321
322 /*
323 * Set the address
324 */
325 if (-1 == ioctl (fd, SIOCSIFADDR, &ifr6))
326 {
327 fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__,
328 strerror (errno));
329 (void) close (fd);
330 exit (1);
331 }
332
333 /*
334 * Get the flags
335 */
336 if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr))
337 {
338 fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__,
339 strerror (errno));
340 (void) close (fd);
341 exit (1);
342 }
343
344 /*
345 * Add the UP and RUNNING flags
346 */
347 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
348 if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr))
349 {
350 fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__,
351 strerror (errno));
352 (void) close (fd);
353 exit (1);
354 }
355
356 if (0 != close (fd))
357 {
358 fprintf (stderr, "close failed: %s\n", strerror (errno));
359 exit (1);
360 }
361}
362
363
364/**
365 * @brief Sets the IPv4-Address given in address on the interface dev
366 *
367 * @param dev the interface to configure
368 * @param address the IPv4-Address
369 * @param mask the netmask
370 */
371static void
372set_address4 (const char *dev, const char *address, const char *mask)
373{
374 int fd;
375 struct sockaddr_in *addr;
376 struct ifreq ifr;
377
378 memset (&ifr, 0, sizeof(struct ifreq));
379 addr = (struct sockaddr_in *) &(ifr.ifr_addr);
380 addr->sin_family = AF_INET;
381
382 /*
383 * Parse the address
384 */
385 if (1 != inet_pton (AF_INET, address, &addr->sin_addr.s_addr))
386 {
387 fprintf (stderr, "Failed to parse address `%s': %s\n", address,
388 strerror (errno));
389 exit (1);
390 }
391
392 if (-1 == (fd = socket (PF_INET, SOCK_DGRAM, 0)))
393 {
394 fprintf (stderr, "Error creating socket: %s\n", strerror (errno));
395 exit (1);
396 }
397
398 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
399
400 /*
401 * Set the address
402 */
403 if (-1 == ioctl (fd, SIOCSIFADDR, &ifr))
404 {
405 fprintf (stderr, "ioctl failed at %d: %s\n", __LINE__, strerror (errno));
406 (void) close (fd);
407 exit (1);
408 }
409
410 /*
411 * Parse the netmask
412 */
413 addr = (struct sockaddr_in *) &(ifr.ifr_netmask);
414 if (1 != inet_pton (AF_INET, mask, &addr->sin_addr.s_addr))
415 {
416 fprintf (stderr, "Failed to parse address `%s': %s\n", mask,
417 strerror (errno));
418 (void) close (fd);
419 exit (1);
420 }
421
422 /*
423 * Set the netmask
424 */
425 if (-1 == ioctl (fd, SIOCSIFNETMASK, &ifr))
426 {
427 fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__,
428 strerror (errno));
429 (void) close (fd);
430 exit (1);
431 }
432
433 /*
434 * Get the flags
435 */
436 if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr))
437 {
438 fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__,
439 strerror (errno));
440 (void) close (fd);
441 exit (1);
442 }
443
444 /*
445 * Add the UP and RUNNING flags
446 */
447 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
448 if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr))
449 {
450 fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__,
451 strerror (errno));
452 (void) close (fd);
453 exit (1);
454 }
455
456 if (0 != close (fd))
457 {
458 fprintf (stderr, "close failed: %s\n", strerror (errno));
459 (void) close (fd);
460 exit (1);
461 }
462}
463
464
465/**
466 * Start forwarding to and from the tunnel.
467 *
468 * @param fd_tun tunnel FD
469 */
470static void
471run (int fd_tun)
472{
473 /*
474 * The buffer filled by reading from fd_tun
475 */
476 unsigned char buftun[MAX_SIZE];
477 ssize_t buftun_size = 0;
478 unsigned char *buftun_read = NULL;
479
480 /*
481 * The buffer filled by reading from stdin
482 */
483 unsigned char bufin[MAX_SIZE];
484 ssize_t bufin_size = 0;
485 size_t bufin_rpos = 0;
486 unsigned char *bufin_read = NULL;
487
488 fd_set fds_w;
489 fd_set fds_r;
490
491 /* read refers to reading from fd_tun, writing to stdout */
492 int read_open = 1;
493
494 /* write refers to reading from stdin, writing to fd_tun */
495 int write_open = 1;
496
497 while ((1 == read_open) && (1 == write_open))
498 {
499 FD_ZERO (&fds_w);
500 FD_ZERO (&fds_r);
501
502 /*
503 * We are supposed to read and the buffer is empty
504 * -> select on read from tun
505 */
506 if (read_open && (0 == buftun_size))
507 FD_SET (fd_tun, &fds_r);
508
509 /*
510 * We are supposed to read and the buffer is not empty
511 * -> select on write to stdout
512 */
513 if (read_open && (0 != buftun_size))
514 FD_SET (1, &fds_w);
515
516 /*
517 * We are supposed to write and the buffer is empty
518 * -> select on read from stdin
519 */
520 if (write_open && (NULL == bufin_read))
521 FD_SET (0, &fds_r);
522
523 /*
524 * We are supposed to write and the buffer is not empty
525 * -> select on write to tun
526 */
527 if (write_open && (NULL != bufin_read))
528 FD_SET (fd_tun, &fds_w);
529
530 int r = select (fd_tun + 1, &fds_r, &fds_w, NULL, NULL);
531
532 if (-1 == r)
533 {
534 if (EINTR == errno)
535 continue;
536 fprintf (stderr, "select failed: %s\n", strerror (errno));
537 exit (1);
538 }
539
540 if (r > 0)
541 {
542 if (FD_ISSET (fd_tun, &fds_r))
543 {
544 buftun_size =
545 read (fd_tun, buftun + sizeof(struct GNUNET_MessageHeader),
546 MAX_SIZE - sizeof(struct GNUNET_MessageHeader));
547 if (-1 == buftun_size)
548 {
549 fprintf (stderr,
550 "read-error: %s\n",
551 strerror (errno));
552 shutdown (fd_tun, SHUT_RD);
553 shutdown (1, SHUT_WR);
554 read_open = 0;
555 buftun_size = 0;
556 }
557 else if (0 == buftun_size)
558 {
559#if DEBUG
560 fprintf (stderr, "EOF on tun\n");
561#endif
562 shutdown (fd_tun, SHUT_RD);
563 shutdown (1, SHUT_WR);
564 read_open = 0;
565 buftun_size = 0;
566 }
567 else
568 {
569 buftun_read = buftun;
570 struct GNUNET_MessageHeader *hdr =
571 (struct GNUNET_MessageHeader *) buftun;
572 buftun_size += sizeof(struct GNUNET_MessageHeader);
573 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
574 hdr->size = htons (buftun_size);
575 }
576 }
577 else if (FD_ISSET (1, &fds_w))
578 {
579 ssize_t written = write (1, buftun_read, buftun_size);
580
581 if (-1 == written)
582 {
583#if ! DEBUG
584 if (errno != EPIPE)
585#endif
586 fprintf (stderr,
587 "write-error to stdout: %s\n",
588 strerror (errno));
589 shutdown (fd_tun, SHUT_RD);
590 shutdown (1, SHUT_WR);
591 read_open = 0;
592 buftun_size = 0;
593 }
594 else if (0 == written)
595 {
596 fprintf (stderr, "write returned 0!?\n");
597 exit (1);
598 }
599 else
600 {
601 buftun_size -= written;
602 buftun_read += written;
603 }
604 }
605
606 if (FD_ISSET (0, &fds_r))
607 {
608 bufin_size = read (0, bufin + bufin_rpos, MAX_SIZE - bufin_rpos);
609 if (-1 == bufin_size)
610 {
611 fprintf (stderr, "read-error: %s\n", strerror (errno));
612 shutdown (0, SHUT_RD);
613 shutdown (fd_tun, SHUT_WR);
614 write_open = 0;
615 bufin_size = 0;
616 }
617 else if (0 == bufin_size)
618 {
619#if DEBUG
620 fprintf (stderr, "EOF on stdin\n");
621#endif
622 shutdown (0, SHUT_RD);
623 shutdown (fd_tun, SHUT_WR);
624 write_open = 0;
625 bufin_size = 0;
626 }
627 else
628 {
629 struct GNUNET_MessageHeader *hdr;
630
631PROCESS_BUFFER:
632 bufin_rpos += bufin_size;
633 if (bufin_rpos < sizeof(struct GNUNET_MessageHeader))
634 continue;
635 hdr = (struct GNUNET_MessageHeader *) bufin;
636 if (ntohs (hdr->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
637 {
638 fprintf (stderr, "protocol violation!\n");
639 exit (1);
640 }
641 if (ntohs (hdr->size) > bufin_rpos)
642 continue;
643 bufin_read = bufin + sizeof(struct GNUNET_MessageHeader);
644 bufin_size = ntohs (hdr->size) - sizeof(struct GNUNET_MessageHeader);
645 bufin_rpos -= bufin_size + sizeof(struct GNUNET_MessageHeader);
646 }
647 }
648 else if (FD_ISSET (fd_tun, &fds_w))
649 {
650 ssize_t written = write (fd_tun, bufin_read, bufin_size);
651
652 if (-1 == written)
653 {
654 fprintf (stderr, "write-error to tun: %s\n", strerror (errno));
655 shutdown (0, SHUT_RD);
656 shutdown (fd_tun, SHUT_WR);
657 write_open = 0;
658 bufin_size = 0;
659 }
660 else if (0 == written)
661 {
662 fprintf (stderr, "write returned 0!?\n");
663 exit (1);
664 }
665 else
666 {
667 bufin_size -= written;
668 bufin_read += written;
669 if (0 == bufin_size)
670 {
671 memmove (bufin, bufin_read, bufin_rpos);
672 bufin_read = NULL; /* start reading again */
673 bufin_size = 0;
674 goto PROCESS_BUFFER;
675 }
676 }
677 }
678 }
679 }
680}
681
682
683/**
684 * Open VPN tunnel interface.
685 *
686 * @param argc must be 6
687 * @param argv 0: binary name ("gnunet-helper-exit")
688 * 1: tunnel interface name ("gnunet-exit")
689 * 2: "physical" interface name ("eth0"), or "-" to not setup NAT
690 * and routing
691 * 3: IPv6 address ("::1"), or "-" to skip IPv6
692 * 4: IPv6 netmask length in bits ("64") [ignored if #4 is "-"]
693 * 5: IPv4 address ("1.2.3.4"), or "-" to skip IPv4
694 * 6: IPv4 netmask ("255.255.0.0") [ignored if #4 is "-"]
695 */
696int
697main (int argc, char **argv)
698{
699 char dev[IFNAMSIZ];
700 int fd_tun;
701 int global_ret;
702
703 if (7 != argc)
704 {
705 fprintf (stderr, "Fatal: must supply 6 arguments!\n");
706 return 1;
707 }
708 if ((0 == strcmp (argv[3], "-")) &&
709 (0 == strcmp (argv[5], "-")))
710 {
711 fprintf (stderr, "Fatal: disabling both IPv4 and IPv6 makes no sense.\n");
712 return 1;
713 }
714 if (0 != strcmp (argv[2], "-"))
715 {
716#ifdef IPTABLES
717 if (0 == access (IPTABLES, X_OK))
718 sbin_iptables = IPTABLES;
719 else
720#endif
721 if (0 == access ("/sbin/iptables", X_OK))
722 sbin_iptables = "/sbin/iptables";
723 else if (0 == access ("/usr/sbin/iptables", X_OK))
724 sbin_iptables = "/usr/sbin/iptables";
725 else
726 {
727 fprintf (stderr,
728 "Fatal: executable iptables not found in approved directories: %s\n",
729 strerror (errno));
730 return 1;
731 }
732#ifdef SYSCTL
733 if (0 == access (SYSCTL, X_OK))
734 sbin_sysctl = SYSCTL;
735 else
736#endif
737 if (0 == access ("/sbin/sysctl", X_OK))
738 sbin_sysctl = "/sbin/sysctl";
739 else if (0 == access ("/usr/sbin/sysctl", X_OK))
740 sbin_sysctl = "/usr/sbin/sysctl";
741 else
742 {
743 fprintf (stderr,
744 "Fatal: executable sysctl not found in approved directories: %s\n",
745 strerror (errno));
746 return 1;
747 }
748 }
749
750 strncpy (dev, argv[1], IFNAMSIZ);
751 dev[IFNAMSIZ - 1] = '\0';
752
753 if (-1 == (fd_tun = init_tun (dev)))
754 {
755 fprintf (stderr,
756 "Fatal: could not initialize tun-interface `%s' with IPv6 %s/%s and IPv4 %s/%s\n",
757 dev,
758 argv[3],
759 argv[4],
760 argv[5],
761 argv[6]);
762 return 1;
763 }
764
765 if (0 != strcmp (argv[3], "-"))
766 {
767 {
768 const char *address = argv[3];
769 long prefix_len = atol (argv[4]);
770
771 if ((prefix_len < 1) || (prefix_len > 127))
772 {
773 fprintf (stderr, "Fatal: prefix_len out of range\n");
774 return 1;
775 }
776 set_address6 (dev, address, prefix_len);
777 }
778 if (0 != strcmp (argv[2], "-"))
779 {
780 char *const sysctl_args[] = {
781 "sysctl", "-w", "net.ipv6.conf.all.forwarding=1", NULL
782 };
783 if (0 != fork_and_exec (sbin_sysctl,
784 sysctl_args))
785 {
786 fprintf (stderr,
787 "Failed to enable IPv6 forwarding. Will continue anyway.\n");
788 }
789 }
790 }
791
792 if (0 != strcmp (argv[5], "-"))
793 {
794 {
795 const char *address = argv[5];
796 const char *mask = argv[6];
797
798 set_address4 (dev, address, mask);
799 }
800 if (0 != strcmp (argv[2], "-"))
801 {
802 {
803 char *const sysctl_args[] = {
804 "sysctl", "-w", "net.ipv4.ip_forward=1", NULL
805 };
806 if (0 != fork_and_exec (sbin_sysctl,
807 sysctl_args))
808 {
809 fprintf (stderr,
810 "Failed to enable IPv4 forwarding. Will continue anyway.\n");
811 }
812 }
813 {
814 char *const iptables_args[] = {
815 "iptables", "-t", "nat", "-A", "POSTROUTING", "-o", argv[2], "-j",
816 "MASQUERADE", NULL
817 };
818 if (0 != fork_and_exec (sbin_iptables,
819 iptables_args))
820 {
821 fprintf (stderr,
822 "Failed to enable IPv4 masquerading (NAT). Will continue anyway.\n");
823 }
824 }
825 }
826 }
827
828 uid_t uid = getuid ();
829#ifdef HAVE_SETRESUID
830 if (0 != setresuid (uid, uid, uid))
831 {
832 fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno));
833 global_ret = 2;
834 goto cleanup;
835 }
836#else
837 if (0 != (setuid (uid) | seteuid (uid)))
838 {
839 fprintf (stderr, "Failed to setuid: %s\n", strerror (errno));
840 global_ret = 2;
841 goto cleanup;
842 }
843#endif
844
845 if (SIG_ERR == signal (SIGPIPE, SIG_IGN))
846 {
847 fprintf (stderr, "Failed to protect against SIGPIPE: %s\n",
848 strerror (errno));
849 /* no exit, we might as well die with SIGPIPE should it ever happen */
850 }
851 run (fd_tun);
852 global_ret = 0;
853cleanup:
854 (void) close (fd_tun);
855 return global_ret;
856}
857
858
859/* end of gnunet-helper-exit.c */