diff options
Diffstat (limited to 'src/vpn/gnunet-daemon-vpn-helper.c')
-rw-r--r-- | src/vpn/gnunet-daemon-vpn-helper.c | 691 |
1 files changed, 0 insertions, 691 deletions
diff --git a/src/vpn/gnunet-daemon-vpn-helper.c b/src/vpn/gnunet-daemon-vpn-helper.c deleted file mode 100644 index 3bb3aa262..000000000 --- a/src/vpn/gnunet-daemon-vpn-helper.c +++ /dev/null | |||
@@ -1,691 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2010 Christian Grothoff | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file vpn/gnunet-daemon-vpn-helper.c | ||
23 | * @brief | ||
24 | * @author Philipp Toelke | ||
25 | */ | ||
26 | #include <platform.h> | ||
27 | #include <gnunet_common.h> | ||
28 | #include <gnunet_client_lib.h> | ||
29 | #include <gnunet_os_lib.h> | ||
30 | #include <gnunet_mesh_service.h> | ||
31 | #include <gnunet_protocols.h> | ||
32 | #include <gnunet_server_lib.h> | ||
33 | #include <gnunet_container_lib.h> | ||
34 | #include <block_dns.h> | ||
35 | #include <gnunet_configuration_lib.h> | ||
36 | #include <gnunet_applications.h> | ||
37 | #include <gnunet_dns_service.h> | ||
38 | |||
39 | #include "gnunet-daemon-vpn.h" | ||
40 | #include "gnunet-daemon-vpn-helper.h" | ||
41 | #include "gnunet-vpn-packet.h" | ||
42 | #include "gnunet-vpn-checksum.h" | ||
43 | #include "gnunet-helper-vpn-api.h" | ||
44 | |||
45 | struct GNUNET_VPN_HELPER_Handle *helper_handle; | ||
46 | |||
47 | extern struct GNUNET_CLIENT_TransmitHandle *dns_transmit_handle; | ||
48 | |||
49 | /** | ||
50 | * The tunnels that will be used to send tcp- and udp-packets | ||
51 | */ | ||
52 | static struct GNUNET_MESH_Tunnel *tcp_tunnel; | ||
53 | static struct GNUNET_MESH_Tunnel *udp_tunnel; | ||
54 | |||
55 | /** | ||
56 | * Start the helper-process | ||
57 | * | ||
58 | * If cls != NULL it is assumed that this function is called as a result of a dying | ||
59 | * helper. cls is then taken as handle to the old helper and is cleaned up. | ||
60 | * {{{ | ||
61 | */ | ||
62 | void | ||
63 | start_helper_and_schedule (void *cls, | ||
64 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
65 | { | ||
66 | shs_task = GNUNET_SCHEDULER_NO_TASK; | ||
67 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
68 | return; | ||
69 | |||
70 | if (cls != NULL) | ||
71 | cleanup_helper (cls); | ||
72 | cls = NULL; | ||
73 | |||
74 | char *ifname; | ||
75 | char *ipv6addr; | ||
76 | char *ipv6prefix; | ||
77 | char *ipv4addr; | ||
78 | char *ipv4mask; | ||
79 | |||
80 | if (GNUNET_SYSERR == | ||
81 | GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IFNAME", &ifname)) | ||
82 | { | ||
83 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
84 | "No entry 'IFNAME' in configuration!\n"); | ||
85 | exit (1); | ||
86 | } | ||
87 | |||
88 | if (GNUNET_SYSERR == | ||
89 | GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR", &ipv6addr)) | ||
90 | { | ||
91 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
92 | "No entry 'IPV6ADDR' in configuration!\n"); | ||
93 | exit (1); | ||
94 | } | ||
95 | |||
96 | if (GNUNET_SYSERR == | ||
97 | GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6PREFIX", | ||
98 | &ipv6prefix)) | ||
99 | { | ||
100 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
101 | "No entry 'IPV6PREFIX' in configuration!\n"); | ||
102 | exit (1); | ||
103 | } | ||
104 | |||
105 | if (GNUNET_SYSERR == | ||
106 | GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR", &ipv4addr)) | ||
107 | { | ||
108 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
109 | "No entry 'IPV4ADDR' in configuration!\n"); | ||
110 | exit (1); | ||
111 | } | ||
112 | |||
113 | if (GNUNET_SYSERR == | ||
114 | GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK", &ipv4mask)) | ||
115 | { | ||
116 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
117 | "No entry 'IPV4MASK' in configuration!\n"); | ||
118 | exit (1); | ||
119 | } | ||
120 | |||
121 | /* Start the helper | ||
122 | * Messages get passed to the function message_token | ||
123 | * When the helper dies, this function will be called again with the | ||
124 | * helper_handle as cls. | ||
125 | */ | ||
126 | helper_handle = | ||
127 | start_helper (ifname, ipv6addr, ipv6prefix, ipv4addr, ipv4mask, | ||
128 | "vpn-gnunet", start_helper_and_schedule, message_token, | ||
129 | NULL); | ||
130 | |||
131 | GNUNET_free (ipv6addr); | ||
132 | GNUNET_free (ipv6prefix); | ||
133 | GNUNET_free (ipv4addr); | ||
134 | GNUNET_free (ipv4mask); | ||
135 | GNUNET_free (ifname); | ||
136 | |||
137 | /* Tell the dns-service to rehijack the dns-port | ||
138 | * The routing-table gets flushed if an interface disappears. | ||
139 | */ | ||
140 | GNUNET_DNS_restart_hijack (dns_handle); | ||
141 | GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, | ||
142 | helper_handle->fh_to_helper, &helper_write, | ||
143 | NULL); | ||
144 | } | ||
145 | |||
146 | /*}}}*/ | ||
147 | |||
148 | static void * | ||
149 | initialize_tunnel_state (int addrlen, struct GNUNET_MESH_TransmitHandle *th) | ||
150 | { | ||
151 | struct tunnel_state *ts = GNUNET_malloc (sizeof *ts); | ||
152 | |||
153 | ts->addrlen = addrlen; | ||
154 | ts->th = th; | ||
155 | return ts; | ||
156 | } | ||
157 | |||
158 | /** | ||
159 | * Send an dns-answer-packet to the helper | ||
160 | */ | ||
161 | void | ||
162 | helper_write (void *cls GNUNET_UNUSED, | ||
163 | const struct GNUNET_SCHEDULER_TaskContext *tsdkctx) | ||
164 | { | ||
165 | if (tsdkctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) | ||
166 | return; | ||
167 | |||
168 | struct answer_packet_list *ans = answer_proc_head; | ||
169 | |||
170 | if (NULL == ans) | ||
171 | return; | ||
172 | |||
173 | size_t len = ntohs (ans->pkt.hdr.size); | ||
174 | |||
175 | GNUNET_assert (ans->pkt.subtype == GNUNET_DNS_ANSWER_TYPE_IP); | ||
176 | |||
177 | GNUNET_assert (20 == sizeof (struct ip_hdr)); | ||
178 | GNUNET_assert (8 == sizeof (struct udp_pkt)); | ||
179 | |||
180 | size_t data_len = len - sizeof (struct answer_packet) + 1; | ||
181 | |||
182 | void *buf; | ||
183 | size_t pkt_len; | ||
184 | |||
185 | if (ans->pkt.addrlen == 16) | ||
186 | { | ||
187 | size_t net_len = | ||
188 | sizeof (struct ip6_hdr) + sizeof (struct udp_dns) + data_len; | ||
189 | pkt_len = | ||
190 | sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) + | ||
191 | net_len; | ||
192 | |||
193 | struct ip6_udp_dns *pkt = alloca (pkt_len); | ||
194 | |||
195 | GNUNET_assert (pkt != NULL); | ||
196 | memset (pkt, 0, pkt_len); | ||
197 | |||
198 | /* set the gnunet-header */ | ||
199 | pkt->shdr.size = htons (pkt_len); | ||
200 | pkt->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); | ||
201 | |||
202 | /* set the tun-header (no flags and ethertype of IPv4) */ | ||
203 | pkt->tun.flags = 0; | ||
204 | pkt->tun.type = htons (0x86dd); | ||
205 | |||
206 | memcpy (&pkt->ip6_hdr.sadr, ans->pkt.from, 16); | ||
207 | memcpy (&pkt->ip6_hdr.dadr, ans->pkt.to, 16); | ||
208 | |||
209 | /* set the udp-header */ | ||
210 | pkt->udp_dns.udp_hdr.spt = htons (53); | ||
211 | pkt->udp_dns.udp_hdr.dpt = ans->pkt.dst_port; | ||
212 | pkt->udp_dns.udp_hdr.len = htons (net_len - sizeof (struct ip6_hdr)); | ||
213 | pkt->udp_dns.udp_hdr.crc = 0; | ||
214 | uint32_t sum = 0; | ||
215 | |||
216 | sum = calculate_checksum_update (sum, (uint16_t *) & pkt->ip6_hdr.sadr, 16); | ||
217 | sum = calculate_checksum_update (sum, (uint16_t *) & pkt->ip6_hdr.dadr, 16); | ||
218 | uint32_t tmp = (pkt->udp_dns.udp_hdr.len & 0xffff); | ||
219 | |||
220 | sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4); | ||
221 | tmp = htons (((pkt->ip6_hdr.nxthdr & 0x00ff))); | ||
222 | sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4); | ||
223 | |||
224 | sum = | ||
225 | calculate_checksum_update (sum, (uint16_t *) & pkt->udp_dns.udp_hdr, | ||
226 | ntohs (net_len - sizeof (struct ip6_hdr))); | ||
227 | pkt->udp_dns.udp_hdr.crc = calculate_checksum_end (sum); | ||
228 | |||
229 | pkt->ip6_hdr.version = 6; | ||
230 | pkt->ip6_hdr.paylgth = net_len - sizeof (struct ip6_hdr); | ||
231 | pkt->ip6_hdr.nxthdr = IPPROTO_UDP; | ||
232 | pkt->ip6_hdr.hoplmt = 0xff; | ||
233 | |||
234 | memcpy (&pkt->udp_dns.data, ans->pkt.data, data_len); | ||
235 | buf = pkt; | ||
236 | } | ||
237 | else if (ans->pkt.addrlen == 4) | ||
238 | { | ||
239 | size_t net_len = | ||
240 | sizeof (struct ip_hdr) + sizeof (struct udp_dns) + data_len; | ||
241 | pkt_len = | ||
242 | sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) + | ||
243 | net_len; | ||
244 | |||
245 | struct ip_udp_dns *pkt = alloca (pkt_len); | ||
246 | |||
247 | GNUNET_assert (pkt != NULL); | ||
248 | memset (pkt, 0, pkt_len); | ||
249 | |||
250 | /* set the gnunet-header */ | ||
251 | pkt->shdr.size = htons (pkt_len); | ||
252 | pkt->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); | ||
253 | |||
254 | /* set the tun-header (no flags and ethertype of IPv4) */ | ||
255 | pkt->tun.flags = 0; | ||
256 | pkt->tun.type = htons (0x0800); | ||
257 | |||
258 | /* set the ip-header */ | ||
259 | pkt->ip_hdr.version = 4; | ||
260 | pkt->ip_hdr.hdr_lngth = 5; | ||
261 | pkt->ip_hdr.diff_serv = 0; | ||
262 | pkt->ip_hdr.tot_lngth = htons (net_len); | ||
263 | pkt->ip_hdr.ident = 0; | ||
264 | pkt->ip_hdr.flags = 0; | ||
265 | pkt->ip_hdr.frag_off = 0; | ||
266 | pkt->ip_hdr.ttl = 255; | ||
267 | pkt->ip_hdr.proto = IPPROTO_UDP; | ||
268 | pkt->ip_hdr.chks = 0; /* Will be calculated later */ | ||
269 | |||
270 | memcpy (&pkt->ip_hdr.sadr, ans->pkt.from, 4); | ||
271 | memcpy (&pkt->ip_hdr.dadr, ans->pkt.to, 4); | ||
272 | |||
273 | pkt->ip_hdr.chks = | ||
274 | calculate_ip_checksum ((uint16_t *) & pkt->ip_hdr, 5 * 4); | ||
275 | |||
276 | /* set the udp-header */ | ||
277 | pkt->udp_dns.udp_hdr.spt = htons (53); | ||
278 | pkt->udp_dns.udp_hdr.dpt = ans->pkt.dst_port; | ||
279 | pkt->udp_dns.udp_hdr.len = htons (net_len - sizeof (struct ip_hdr)); | ||
280 | pkt->udp_dns.udp_hdr.crc = 0; /* Optional for IPv4 */ | ||
281 | |||
282 | memcpy (&pkt->udp_dns.data, ans->pkt.data, data_len); | ||
283 | buf = pkt; | ||
284 | } | ||
285 | else | ||
286 | { | ||
287 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Wrong addrlen = %d\n", | ||
288 | ans->pkt.addrlen); | ||
289 | GNUNET_assert (0); | ||
290 | return; /* convince compiler that we're done here */ | ||
291 | } | ||
292 | |||
293 | GNUNET_CONTAINER_DLL_remove (answer_proc_head, answer_proc_tail, ans); | ||
294 | GNUNET_free (ans); | ||
295 | |||
296 | if (GNUNET_DISK_file_write (helper_handle->fh_to_helper, buf, pkt_len) < 0) | ||
297 | { | ||
298 | cleanup_helper (helper_handle); | ||
299 | GNUNET_SCHEDULER_add_now (start_helper_and_schedule, NULL); | ||
300 | return; | ||
301 | } | ||
302 | |||
303 | /* if more packets are available, reschedule */ | ||
304 | if (answer_proc_head != NULL) | ||
305 | GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, | ||
306 | helper_handle->fh_to_helper, &helper_write, | ||
307 | NULL); | ||
308 | } | ||
309 | |||
310 | /** | ||
311 | * Receive packets from the helper-process | ||
312 | */ | ||
313 | void | ||
314 | message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED, | ||
315 | const struct GNUNET_MessageHeader *message) | ||
316 | { | ||
317 | GNUNET_assert (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_HELPER); | ||
318 | |||
319 | struct tun_pkt *pkt_tun = (struct tun_pkt *) message; | ||
320 | GNUNET_HashCode *key; | ||
321 | |||
322 | /* ethertype is ipv6 */ | ||
323 | if (ntohs (pkt_tun->tun.type) == 0x86dd) | ||
324 | { | ||
325 | struct ip6_pkt *pkt6 = (struct ip6_pkt *) message; | ||
326 | |||
327 | GNUNET_assert (pkt6->ip6_hdr.version == 6); | ||
328 | struct ip6_tcp *pkt6_tcp; | ||
329 | struct ip6_udp *pkt6_udp; | ||
330 | struct ip6_icmp *pkt6_icmp; | ||
331 | |||
332 | pkt6_udp = NULL; /* make compiler happy */ | ||
333 | switch (pkt6->ip6_hdr.nxthdr) | ||
334 | { | ||
335 | case IPPROTO_UDP: | ||
336 | pkt6_udp = (struct ip6_udp *) pkt6; | ||
337 | /* Send dns-packets to the service-dns */ | ||
338 | if (ntohs (pkt6_udp->udp_hdr.dpt) == 53) | ||
339 | { | ||
340 | /* 9 = 8 for the udp-header + 1 for the unsigned char data[1]; */ | ||
341 | GNUNET_DNS_queue_request_v6 (dns_handle, | ||
342 | &pkt6->ip6_hdr.dadr, | ||
343 | &pkt6->ip6_hdr.sadr, | ||
344 | ntohs (pkt6_udp->udp_hdr.spt), | ||
345 | ntohs (pkt6_udp->udp_hdr.len) - 8, | ||
346 | (const void*) pkt6_udp->data); | ||
347 | |||
348 | break; | ||
349 | } | ||
350 | /* fall through */ | ||
351 | case IPPROTO_TCP: | ||
352 | pkt6_tcp = (struct ip6_tcp *) pkt6; | ||
353 | |||
354 | if ((key = address6_mapping_exists (&pkt6->ip6_hdr.dadr)) != NULL) | ||
355 | { | ||
356 | struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key); | ||
357 | |||
358 | GNUNET_assert (me != NULL); | ||
359 | GNUNET_free (key); | ||
360 | |||
361 | size_t size = | ||
362 | sizeof (struct GNUNET_MESH_Tunnel *) + | ||
363 | sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + | ||
364 | ntohs (pkt6->ip6_hdr.paylgth); | ||
365 | |||
366 | struct GNUNET_MESH_Tunnel **cls = GNUNET_malloc (size); | ||
367 | struct GNUNET_MessageHeader *hdr = | ||
368 | (struct GNUNET_MessageHeader *) (cls + 1); | ||
369 | GNUNET_HashCode *hc = (GNUNET_HashCode *) (hdr + 1); | ||
370 | |||
371 | hdr->size = | ||
372 | htons (sizeof (struct GNUNET_MessageHeader) + | ||
373 | sizeof (GNUNET_HashCode) + ntohs (pkt6->ip6_hdr.paylgth)); | ||
374 | |||
375 | GNUNET_MESH_ApplicationType app_type = 0; /* fix compiler uninitialized warning... */ | ||
376 | |||
377 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "me->addrlen is %d\n", | ||
378 | me->addrlen); | ||
379 | if (me->addrlen == 0) | ||
380 | { | ||
381 | /* This is a mapping to a gnunet-service */ | ||
382 | memcpy (hc, &me->desc.service_descriptor, sizeof (GNUNET_HashCode)); | ||
383 | |||
384 | if (IPPROTO_UDP == pkt6->ip6_hdr.nxthdr && | ||
385 | (me->desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_UDP)) && | ||
386 | (port_in_ports (me->desc.ports, pkt6_udp->udp_hdr.dpt) || | ||
387 | testBit (me->additional_ports, ntohs (pkt6_udp->udp_hdr.dpt)))) | ||
388 | { | ||
389 | hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP); | ||
390 | |||
391 | memcpy (hc + 1, &pkt6_udp->udp_hdr, ntohs (pkt6_udp->udp_hdr.len)); | ||
392 | |||
393 | } | ||
394 | else if (IPPROTO_TCP == pkt6->ip6_hdr.nxthdr && | ||
395 | (me->desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_TCP)) | ||
396 | && (port_in_ports (me->desc.ports, pkt6_tcp->tcp_hdr.dpt))) | ||
397 | { | ||
398 | hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP); | ||
399 | |||
400 | memcpy (hc + 1, &pkt6_tcp->tcp_hdr, ntohs (pkt6->ip6_hdr.paylgth)); | ||
401 | |||
402 | } | ||
403 | else | ||
404 | { | ||
405 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pip: %d\n", | ||
406 | port_in_ports (me->desc.ports, pkt6_tcp->tcp_hdr.dpt)); | ||
407 | GNUNET_assert (0); | ||
408 | } | ||
409 | if (me->tunnel == NULL && NULL != cls) | ||
410 | { | ||
411 | *cls = | ||
412 | GNUNET_MESH_tunnel_create (mesh_handle, | ||
413 | initialize_tunnel_state (16, NULL), | ||
414 | &send_pkt_to_peer, NULL, cls); | ||
415 | |||
416 | GNUNET_MESH_peer_request_connect_add (*cls, | ||
417 | (struct GNUNET_PeerIdentity *) | ||
418 | &me->desc.peer); | ||
419 | me->tunnel = *cls; | ||
420 | } | ||
421 | else if (NULL != cls) | ||
422 | { | ||
423 | *cls = me->tunnel; | ||
424 | send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL); | ||
425 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
426 | "Queued to send IPv6 to peer %x, type %d\n", | ||
427 | *((unsigned int *) &me->desc.peer), ntohs (hdr->type)); | ||
428 | } | ||
429 | } | ||
430 | else | ||
431 | { | ||
432 | /* This is a mapping to a "real" address */ | ||
433 | struct remote_addr *s = (struct remote_addr *) hc; | ||
434 | |||
435 | s->addrlen = me->addrlen; | ||
436 | memcpy (s->addr, me->addr, me->addrlen); | ||
437 | s->proto = pkt6->ip6_hdr.nxthdr; | ||
438 | if (s->proto == IPPROTO_UDP) | ||
439 | { | ||
440 | hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP); | ||
441 | memcpy (hc + 1, &pkt6_udp->udp_hdr, ntohs (pkt6_udp->udp_hdr.len)); | ||
442 | app_type = GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY; | ||
443 | if (NULL != udp_tunnel) | ||
444 | me->tunnel = udp_tunnel; | ||
445 | } | ||
446 | else if (s->proto == IPPROTO_TCP) | ||
447 | { | ||
448 | hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP); | ||
449 | memcpy (hc + 1, &pkt6_tcp->tcp_hdr, ntohs (pkt6->ip6_hdr.paylgth)); | ||
450 | app_type = GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY; | ||
451 | if (NULL != tcp_tunnel) | ||
452 | me->tunnel = tcp_tunnel; | ||
453 | } | ||
454 | else | ||
455 | { | ||
456 | GNUNET_assert (0); | ||
457 | } | ||
458 | if (me->tunnel == NULL && NULL != cls) | ||
459 | { | ||
460 | *cls = | ||
461 | GNUNET_MESH_tunnel_create (mesh_handle, | ||
462 | initialize_tunnel_state (16, NULL), | ||
463 | &send_pkt_to_peer, NULL, cls); | ||
464 | |||
465 | GNUNET_MESH_peer_request_connect_by_type (*cls, app_type); | ||
466 | me->tunnel = *cls; | ||
467 | if (GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY == app_type) | ||
468 | udp_tunnel = *cls; | ||
469 | else if (GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY == app_type) | ||
470 | tcp_tunnel = *cls; | ||
471 | } | ||
472 | else if (NULL != cls) | ||
473 | { | ||
474 | *cls = me->tunnel; | ||
475 | send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL); | ||
476 | } | ||
477 | } | ||
478 | } | ||
479 | else | ||
480 | { | ||
481 | char pbuf[INET6_ADDRSTRLEN]; | ||
482 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
483 | "Packet to %s, which has no mapping\n", | ||
484 | inet_ntop (AF_INET6, | ||
485 | &pkt6->ip6_hdr.dadr, | ||
486 | pbuf, | ||
487 | sizeof (pbuf))); | ||
488 | } | ||
489 | break; | ||
490 | case 0x3a: | ||
491 | /* ICMPv6 */ | ||
492 | pkt6_icmp = (struct ip6_icmp *) pkt6; | ||
493 | /* If this packet is an icmp-echo-request and a mapping exists, answer */ | ||
494 | if (pkt6_icmp->icmp_hdr.type == 0x80 && | ||
495 | (key = address6_mapping_exists (&pkt6->ip6_hdr.dadr)) != NULL) | ||
496 | { | ||
497 | GNUNET_free (key); | ||
498 | pkt6_icmp = GNUNET_malloc (ntohs (pkt6->shdr.size)); | ||
499 | memcpy (pkt6_icmp, pkt6, ntohs (pkt6->shdr.size)); | ||
500 | GNUNET_SCHEDULER_add_now (&send_icmp6_response, pkt6_icmp); | ||
501 | } | ||
502 | break; | ||
503 | } | ||
504 | } | ||
505 | /* ethertype is ipv4 */ | ||
506 | else if (ntohs (pkt_tun->tun.type) == 0x0800) | ||
507 | { | ||
508 | struct ip_pkt *pkt = (struct ip_pkt *) message; | ||
509 | struct ip_udp *udp = (struct ip_udp *) message; | ||
510 | struct ip_tcp *pkt_tcp; | ||
511 | struct ip_udp *pkt_udp; | ||
512 | struct ip_icmp *pkt_icmp; | ||
513 | |||
514 | GNUNET_assert (pkt->ip_hdr.version == 4); | ||
515 | |||
516 | /* Send dns-packets to the service-dns */ | ||
517 | if (pkt->ip_hdr.proto == IPPROTO_UDP && ntohs (udp->udp_hdr.dpt) == 53) | ||
518 | { | ||
519 | GNUNET_DNS_queue_request_v4 (dns_handle, | ||
520 | &pkt->ip_hdr.dadr, | ||
521 | &pkt->ip_hdr.sadr, | ||
522 | ntohs (udp->udp_hdr.spt), | ||
523 | ntohs (udp->udp_hdr.len) - 8, | ||
524 | (const void*) udp->data); | ||
525 | } | ||
526 | else | ||
527 | { | ||
528 | uint32_t dadr = pkt->ip_hdr.dadr.s_addr; | ||
529 | unsigned char *c = (unsigned char *) &dadr; | ||
530 | |||
531 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Packet to %d.%d.%d.%d, proto %x\n", | ||
532 | c[0], c[1], c[2], c[3], pkt->ip_hdr.proto); | ||
533 | switch (pkt->ip_hdr.proto) | ||
534 | { | ||
535 | case IPPROTO_TCP: | ||
536 | case IPPROTO_UDP: | ||
537 | pkt_tcp = (struct ip_tcp *) pkt; | ||
538 | pkt_udp = (struct ip_udp *) pkt; | ||
539 | |||
540 | if ((key = address4_mapping_exists (dadr)) != NULL) | ||
541 | { | ||
542 | struct map_entry *me = | ||
543 | GNUNET_CONTAINER_multihashmap_get (hashmap, key); | ||
544 | GNUNET_assert (me != NULL); | ||
545 | GNUNET_free (key); | ||
546 | |||
547 | size_t size = | ||
548 | sizeof (struct GNUNET_MESH_Tunnel *) + | ||
549 | sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + | ||
550 | ntohs (pkt->ip_hdr.tot_lngth) - 4 * pkt->ip_hdr.hdr_lngth; | ||
551 | |||
552 | struct GNUNET_MESH_Tunnel **cls = GNUNET_malloc (size); | ||
553 | struct GNUNET_MessageHeader *hdr = | ||
554 | (struct GNUNET_MessageHeader *) (cls + 1); | ||
555 | GNUNET_HashCode *hc = (GNUNET_HashCode *) (hdr + 1); | ||
556 | |||
557 | hdr->size = | ||
558 | htons (sizeof (struct GNUNET_MessageHeader) + | ||
559 | sizeof (GNUNET_HashCode) + ntohs (pkt->ip_hdr.tot_lngth) - | ||
560 | 4 * pkt->ip_hdr.hdr_lngth); | ||
561 | |||
562 | GNUNET_MESH_ApplicationType app_type = 0; /* make compiler happy */ | ||
563 | |||
564 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "me->addrlen is %d\n", | ||
565 | me->addrlen); | ||
566 | if (me->addrlen == 0) | ||
567 | { | ||
568 | /* This is a mapping to a gnunet-service */ | ||
569 | memcpy (hc, &me->desc.service_descriptor, sizeof (GNUNET_HashCode)); | ||
570 | |||
571 | if ((IPPROTO_UDP == pkt->ip_hdr.proto) && | ||
572 | (me->desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_UDP)) && | ||
573 | (port_in_ports (me->desc.ports, pkt_udp->udp_hdr.dpt) || | ||
574 | testBit (me->additional_ports, ntohs (pkt_udp->udp_hdr.dpt)))) | ||
575 | { | ||
576 | hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP); | ||
577 | |||
578 | memcpy (hc + 1, &pkt_udp->udp_hdr, ntohs (pkt_udp->udp_hdr.len)); | ||
579 | |||
580 | } | ||
581 | else if ((IPPROTO_TCP == pkt->ip_hdr.proto) && | ||
582 | (me-> | ||
583 | desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_TCP)) | ||
584 | && (port_in_ports (me->desc.ports, pkt_tcp->tcp_hdr.dpt))) | ||
585 | { | ||
586 | hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP); | ||
587 | |||
588 | memcpy (hc + 1, &pkt_tcp->tcp_hdr, | ||
589 | ntohs (pkt->ip_hdr.tot_lngth) - | ||
590 | 4 * pkt->ip_hdr.hdr_lngth); | ||
591 | |||
592 | } | ||
593 | if (me->tunnel == NULL && NULL != cls) | ||
594 | { | ||
595 | *cls = | ||
596 | GNUNET_MESH_tunnel_create (mesh_handle, | ||
597 | initialize_tunnel_state (4, NULL), | ||
598 | send_pkt_to_peer, NULL, cls); | ||
599 | GNUNET_MESH_peer_request_connect_add (*cls, | ||
600 | (struct GNUNET_PeerIdentity | ||
601 | *) &me->desc.peer); | ||
602 | me->tunnel = *cls; | ||
603 | } | ||
604 | else if (NULL != cls) | ||
605 | { | ||
606 | *cls = me->tunnel; | ||
607 | send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL); | ||
608 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
609 | "Queued to send IPv4 to peer %x, type %d\n", | ||
610 | *((unsigned int *) &me->desc.peer), | ||
611 | ntohs (hdr->type)); | ||
612 | } | ||
613 | } | ||
614 | else | ||
615 | { | ||
616 | /* This is a mapping to a "real" address */ | ||
617 | struct remote_addr *s = (struct remote_addr *) hc; | ||
618 | |||
619 | s->addrlen = me->addrlen; | ||
620 | memcpy (s->addr, me->addr, me->addrlen); | ||
621 | s->proto = pkt->ip_hdr.proto; | ||
622 | if (s->proto == IPPROTO_UDP) | ||
623 | { | ||
624 | hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP); | ||
625 | memcpy (hc + 1, &pkt_udp->udp_hdr, ntohs (pkt_udp->udp_hdr.len)); | ||
626 | app_type = GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY; | ||
627 | } | ||
628 | else if (s->proto == IPPROTO_TCP) | ||
629 | { | ||
630 | hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP); | ||
631 | memcpy (hc + 1, &pkt_tcp->tcp_hdr, | ||
632 | ntohs (pkt->ip_hdr.tot_lngth) - | ||
633 | 4 * pkt->ip_hdr.hdr_lngth); | ||
634 | app_type = GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY; | ||
635 | } | ||
636 | else | ||
637 | GNUNET_assert (0); | ||
638 | if (me->tunnel == NULL && NULL != cls) | ||
639 | { | ||
640 | *cls = | ||
641 | GNUNET_MESH_tunnel_create (mesh_handle, | ||
642 | initialize_tunnel_state (4, NULL), | ||
643 | send_pkt_to_peer, NULL, cls); | ||
644 | |||
645 | GNUNET_MESH_peer_request_connect_by_type (*cls, app_type); | ||
646 | me->tunnel = *cls; | ||
647 | } | ||
648 | else if (NULL != cls) | ||
649 | { | ||
650 | *cls = me->tunnel; | ||
651 | send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL); | ||
652 | } | ||
653 | } | ||
654 | } | ||
655 | else | ||
656 | { | ||
657 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
658 | "Packet to %x which has no mapping\n", dadr); | ||
659 | } | ||
660 | break; | ||
661 | case 0x01: | ||
662 | /* ICMP */ | ||
663 | pkt_icmp = (struct ip_icmp *) pkt; | ||
664 | if (pkt_icmp->icmp_hdr.type == 0x8 && | ||
665 | (key = address4_mapping_exists (dadr)) != NULL) | ||
666 | { | ||
667 | GNUNET_free (key); | ||
668 | pkt_icmp = GNUNET_malloc (ntohs (pkt->shdr.size)); | ||
669 | memcpy (pkt_icmp, pkt, ntohs (pkt->shdr.size)); | ||
670 | GNUNET_SCHEDULER_add_now (&send_icmp4_response, pkt_icmp); | ||
671 | } | ||
672 | break; | ||
673 | } | ||
674 | } | ||
675 | } | ||
676 | } | ||
677 | |||
678 | void | ||
679 | write_to_helper (void *buf, size_t len) | ||
680 | { | ||
681 | (void) GNUNET_DISK_file_write (helper_handle->fh_to_helper, buf, len); | ||
682 | } | ||
683 | |||
684 | void | ||
685 | schedule_helper_write (struct GNUNET_TIME_Relative time, void *cls) | ||
686 | { | ||
687 | if (GNUNET_SCHEDULER_NO_TASK != shs_task) | ||
688 | return; | ||
689 | GNUNET_SCHEDULER_add_write_file (time, helper_handle->fh_to_helper, | ||
690 | &helper_write, cls); | ||
691 | } | ||