GNUnet  0.10.x
gnunet-service-vpn.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2010, 2011, 2012, 2016, 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 
33 #include "platform.h"
34 #include "gnunet_util_lib.h"
35 #include "gnunet_common.h"
36 #include "gnunet_protocols.h"
37 #include "gnunet_applications.h"
38 #include "gnunet_cadet_service.h"
40 #include "gnunet_constants.h"
41 #include "gnunet_tun_lib.h"
42 #include "gnunet_regex_service.h"
43 #include "vpn.h"
44 #include "exit.h"
45 
46 
50 #define MAX_MESSAGE_QUEUE_SIZE 4
51 
52 
56 struct ChannelState;
57 
62 struct DestinationEntry;
63 
69 {
70 
75 
80 
85 
89  uint16_t destination_port;
90 };
91 
92 
98 {
99 
105 
110 
115 
120 
126 
130  union
131  {
132 
133  struct
134  {
138  struct GNUNET_HashCode service_descriptor;
139 
143  struct GNUNET_PeerIdentity target;
144 
145  } service_destination;
146 
147  struct
148  {
149 
153  int af;
154 
158  union
159  {
163  struct in_addr v4;
164 
168  struct in6_addr v6;
169  } ip;
170 
171  } exit_destination;
172 
173  } details;
174 };
175 
176 
181 {
186 
191 
195  size_t len;
196 
200  const void *msg;
201 };
202 
203 
207 struct ChannelState
208 {
209 
214  struct GNUNET_CADET_Channel *channel;
215 
220 
225  struct GNUNET_CONTAINER_HeapNode *heap_node;
226 
231 
236 
244 
248  int af;
249 
255 
259  unsigned int tmq_length;
260 
264  uint8_t protocol;
265 
269  union
270  {
274  struct in_addr v4;
275 
279  struct in6_addr v6;
280 
281  } source_ip;
282 
287  union
288  {
292  struct in_addr v4;
293 
297  struct in6_addr v6;
298 
299  } destination_ip;
300 
304  uint16_t source_port;
305 
310 };
311 
312 
316 static int global_ret;
317 
321 static const struct GNUNET_CONFIGURATION_Handle *cfg;
322 
327 
333 
338 
344 
350 
355 
360 
364 static char *vpn_argv[7];
365 
369 static unsigned long long ipv6prefix;
370 
375 static unsigned long long max_destination_mappings;
376 
381 static unsigned long long max_channel_mappings;
382 
383 
392 static void
394  const void *address,
395  struct GNUNET_HashCode *key)
396 {
397  switch (af)
398  {
399  case AF_INET:
400  GNUNET_CRYPTO_hash (address, sizeof (struct in_addr), key);
401  break;
402  case AF_INET6:
403  GNUNET_CRYPTO_hash (address, sizeof (struct in6_addr), key);
404  break;
405  default:
406  GNUNET_assert (0);
407  break;
408  }
409 }
410 
411 
424 static void
426  uint8_t protocol,
427  const void *source_ip,
428  uint16_t source_port,
429  const void *destination_ip,
430  uint16_t destination_port,
431  struct GNUNET_HashCode *key)
432 {
433  char *off;
434 
435  memset (key, 0, sizeof (struct GNUNET_HashCode));
436  /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
437  so we put the ports in there (and hope for few collisions) */
438  off = (char *) key;
439  GNUNET_memcpy (off, &source_port, sizeof (uint16_t));
440  off += sizeof (uint16_t);
441  GNUNET_memcpy (off, &destination_port, sizeof (uint16_t));
442  off += sizeof (uint16_t);
443  switch (af)
444  {
445  case AF_INET:
446  GNUNET_memcpy (off, source_ip, sizeof (struct in_addr));
447  off += sizeof (struct in_addr);
448  GNUNET_memcpy (off, destination_ip, sizeof (struct in_addr));
449  off += sizeof (struct in_addr);
450  break;
451  case AF_INET6:
452  GNUNET_memcpy (off, source_ip, sizeof (struct in6_addr));
453  off += sizeof (struct in6_addr);
454  GNUNET_memcpy (off, destination_ip, sizeof (struct in6_addr));
455  off += sizeof (struct in6_addr);
456  break;
457  default:
458  GNUNET_assert (0);
459  break;
460  }
461  GNUNET_memcpy (off, &protocol, sizeof (uint8_t));
462  /* off += sizeof (uint8_t); */
463 }
464 
465 
474 static void
476  uint64_t request_id,
477  int result_af,
478  const void *addr)
479 {
480  struct GNUNET_MQ_Envelope *env;
482  size_t rlen;
483 
484  switch (result_af)
485  {
486  case AF_INET:
487  rlen = sizeof (struct in_addr);
488  break;
489  case AF_INET6:
490  rlen = sizeof (struct in6_addr);
491  break;
492  case AF_UNSPEC:
493  rlen = 0;
494  break;
495  default:
496  GNUNET_assert (0);
497  return;
498  }
500  res->result_af = htonl (result_af);
501  res->request_id = request_id;
502  GNUNET_memcpy (&res[1], addr, rlen);
504 }
505 
506 
512 static void
514 {
515  struct GNUNET_HashCode key;
516  struct ChannelMessageQueueEntry *tnq;
517  struct GNUNET_CADET_Channel *channel;
518 
519  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up channel state\n");
520  if (NULL != (channel = ts->channel))
521  {
522  ts->channel = NULL;
524  return;
525  }
527  gettext_noop ("# Active channels"),
528  -1,
529  GNUNET_NO);
530  while (NULL != (tnq = ts->tmq_head))
531  {
533  ts->tmq_length--;
534  GNUNET_free (tnq);
535  }
536  GNUNET_assert (0 == ts->tmq_length);
537  GNUNET_assert (NULL == ts->destination.heap_node);
538  if (NULL != ts->search)
539  {
541  ts->search = NULL;
542  }
543  if (NULL != ts->heap_node)
544  {
546  ts->heap_node = NULL;
548  ts->protocol,
549  &ts->source_ip,
550  ts->source_port,
551  &ts->destination_ip,
552  ts->destination_port,
553  &key);
554  GNUNET_assert (
555  GNUNET_YES ==
556  GNUNET_CONTAINER_multihashmap_remove (channel_map, &key, ts));
557  }
558  GNUNET_free (ts);
559 }
560 
561 
569 static void
571 {
572  struct GNUNET_MQ_Handle *mq;
573 
574  GNUNET_assert (NULL != ts->channel);
575  mq = GNUNET_CADET_get_mq (ts->channel);
579  GNUNET_MQ_send (mq, env);
581  {
582  env = GNUNET_MQ_unsent_head (mq);
583  GNUNET_assert (NULL != env);
585  gettext_noop (
586  "# Messages dropped in cadet queue (overflow)"),
587  1,
588  GNUNET_NO);
589  GNUNET_MQ_discard (env);
590  }
591 }
592 
593 
600 static const char *
602 {
603  static char dest[256];
604 
605  if (de->is_service)
606  {
607  GNUNET_snprintf (dest,
608  sizeof (dest),
609  "HS: %s-%s",
610  GNUNET_i2s (&de->details.service_destination.target),
611  GNUNET_h2s (
612  &de->details.service_destination.service_descriptor));
613  }
614  else
615  {
616  inet_ntop (de->details.exit_destination.af,
617  &de->details.exit_destination.ip,
618  dest,
619  sizeof (dest));
620  }
621  return dest;
622 }
623 
624 
632 static void
633 channel_cleaner (void *cls, const struct GNUNET_CADET_Channel *channel)
634 {
635  struct ChannelState *ts = cls;
636 
637  ts->channel =
638  NULL; /* we must not call GNUNET_CADET_channel_destroy() anymore */
640  "CADET notified us about death of channel to `%s'\n",
642  free_channel_state (ts);
643 }
644 
645 
655 static void
657  struct GNUNET_TUN_IPv4Header *ipp,
658  struct GNUNET_TUN_UdpHeader *udp)
659 {
661  ts->protocol,
662  sizeof (struct GNUNET_TUN_TcpHeader),
663  &ts->source_ip.v4,
664  &ts->destination_ip.v4);
665  udp->source_port = htons (ts->source_port);
666  udp->destination_port = htons (ts->destination_port);
667  udp->len = htons (0);
668  udp->crc = htons (0);
669 }
670 
671 
681 static void
683  struct GNUNET_TUN_IPv6Header *ipp,
684  struct GNUNET_TUN_UdpHeader *udp)
685 {
687  ts->protocol,
688  sizeof (struct GNUNET_TUN_TcpHeader),
689  &ts->source_ip.v6,
690  &ts->destination_ip.v6);
691  udp->source_port = htons (ts->source_port);
692  udp->destination_port = htons (ts->destination_port);
693  udp->len = htons (0);
694  udp->crc = htons (0);
695 }
696 
697 
706 static int
707 check_icmp_back (void *cls, const struct GNUNET_EXIT_IcmpToVPNMessage *i2v)
708 {
709  struct ChannelState *ts = cls;
710 
711  if (NULL == ts->heap_node)
712  {
713  GNUNET_break_op (0);
714  return GNUNET_SYSERR;
715  }
716  if (AF_UNSPEC == ts->af)
717  {
718  GNUNET_break_op (0);
719  return GNUNET_SYSERR;
720  }
721  return GNUNET_OK;
722 }
723 
724 
732 static void
733 handle_icmp_back (void *cls, const struct GNUNET_EXIT_IcmpToVPNMessage *i2v)
734 {
735  struct ChannelState *ts = cls;
736  size_t mlen;
737 
739  gettext_noop ("# ICMP packets received from cadet"),
740  1,
741  GNUNET_NO);
742  mlen =
743  ntohs (i2v->header.size) - sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
744  {
745  char sbuf[INET6_ADDRSTRLEN];
746  char dbuf[INET6_ADDRSTRLEN];
747 
748  GNUNET_log (
750  "Received ICMP packet from cadet, sending %u bytes from %s -> %s via TUN\n",
751  (unsigned int) mlen,
752  inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
753  inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
754  }
755  switch (ts->af)
756  {
757  case AF_INET: {
758  size_t size = sizeof (struct GNUNET_TUN_IPv4Header) +
759  sizeof (struct GNUNET_TUN_IcmpHeader) +
760  sizeof (struct GNUNET_MessageHeader) +
761  sizeof (struct GNUNET_TUN_Layer2PacketHeader) + mlen;
762  {
763  /* reserve some extra space in case we have an ICMP type here where
764  we will need to make up the payload ourselves */
765  char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
766  struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
767  struct GNUNET_TUN_Layer2PacketHeader *tun =
768  (struct GNUNET_TUN_Layer2PacketHeader *) &msg[1];
769  struct GNUNET_TUN_IPv4Header *ipv4 =
770  (struct GNUNET_TUN_IPv4Header *) &tun[1];
771  struct GNUNET_TUN_IcmpHeader *icmp =
772  (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
773  msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
774  tun->flags = htons (0);
775  tun->proto = htons (ETH_P_IPV4);
777  IPPROTO_ICMP,
778  sizeof (struct GNUNET_TUN_IcmpHeader) +
779  mlen,
780  &ts->destination_ip.v4,
781  &ts->source_ip.v4);
782  *icmp = i2v->icmp_header;
783  GNUNET_memcpy (&icmp[1], &i2v[1], mlen);
784  /* For some ICMP types, we need to adjust (make up) the payload here.
785  Also, depending on the AF used on the other side, we have to
786  do ICMP PT (translate ICMP types) */
787  switch (ntohl (i2v->af))
788  {
789  case AF_INET:
790  switch (icmp->type)
791  {
794  break;
798  struct GNUNET_TUN_IPv4Header *ipp =
799  (struct GNUNET_TUN_IPv4Header *) &icmp[1];
800  struct GNUNET_TUN_UdpHeader *udp =
801  (struct GNUNET_TUN_UdpHeader *) &ipp[1];
802 
803  if (mlen != 0)
804  {
805  /* sender did not strip ICMP payload? */
806  GNUNET_break_op (0);
807  return;
808  }
809  size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
810  GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
811  make_up_icmpv4_payload (ts, ipp, udp);
812  }
813  break;
814  default:
815  GNUNET_break_op (0);
817  stats,
818  gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
819  1,
820  GNUNET_NO);
821  return;
822  }
823  /* end AF_INET */
824  break;
825  case AF_INET6:
826  /* ICMP PT 6-to-4 and possibly making up payloads */
827  switch (icmp->type)
828  {
831  {
832  struct GNUNET_TUN_IPv4Header *ipp =
833  (struct GNUNET_TUN_IPv4Header *) &icmp[1];
834  struct GNUNET_TUN_UdpHeader *udp =
835  (struct GNUNET_TUN_UdpHeader *) &ipp[1];
836 
837  if (mlen != 0)
838  {
839  /* sender did not strip ICMP payload? */
840  GNUNET_break_op (0);
841  return;
842  }
843  size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
844  GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
845  make_up_icmpv4_payload (ts, ipp, udp);
846  }
847  break;
850  {
851  struct GNUNET_TUN_IPv4Header *ipp =
852  (struct GNUNET_TUN_IPv4Header *) &icmp[1];
853  struct GNUNET_TUN_UdpHeader *udp =
854  (struct GNUNET_TUN_UdpHeader *) &ipp[1];
855 
856  if (mlen != 0)
857  {
858  /* sender did not strip ICMP payload? */
859  GNUNET_break_op (0);
860  return;
861  }
862  size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
863  GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
864  make_up_icmpv4_payload (ts, ipp, udp);
865  }
866  break;
870  stats,
871  gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
872  1,
873  GNUNET_NO);
874  return;
877  break;
880  break;
881  default:
882  GNUNET_break_op (0);
884  stats,
885  gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
886  1,
887  GNUNET_NO);
888  return;
889  }
890  /* end AF_INET6 */
891  break;
892  default:
893  GNUNET_break_op (0);
894  return;
895  }
896  msg->size = htons (size);
897  GNUNET_TUN_calculate_icmp_checksum (icmp, &i2v[1], mlen);
898  (void) GNUNET_HELPER_send (helper_handle, msg, GNUNET_YES, NULL, NULL);
899  }
900  }
901  break;
902  case AF_INET6: {
903  size_t size = sizeof (struct GNUNET_TUN_IPv6Header) +
904  sizeof (struct GNUNET_TUN_IcmpHeader) +
905  sizeof (struct GNUNET_MessageHeader) +
906  sizeof (struct GNUNET_TUN_Layer2PacketHeader) + mlen;
907  {
908  char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
909  struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
910  struct GNUNET_TUN_Layer2PacketHeader *tun =
911  (struct GNUNET_TUN_Layer2PacketHeader *) &msg[1];
912  struct GNUNET_TUN_IPv6Header *ipv6 =
913  (struct GNUNET_TUN_IPv6Header *) &tun[1];
914  struct GNUNET_TUN_IcmpHeader *icmp =
915  (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
916  msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
917  tun->flags = htons (0);
918  tun->proto = htons (ETH_P_IPV6);
920  IPPROTO_ICMPV6,
921  sizeof (struct GNUNET_TUN_IcmpHeader) +
922  mlen,
923  &ts->destination_ip.v6,
924  &ts->source_ip.v6);
925  *icmp = i2v->icmp_header;
926  GNUNET_memcpy (&icmp[1], &i2v[1], mlen);
927 
928  /* For some ICMP types, we need to adjust (make up) the payload here.
929  Also, depending on the AF used on the other side, we have to
930  do ICMP PT (translate ICMP types) */
931  switch (ntohl (i2v->af))
932  {
933  case AF_INET:
934  /* ICMP PT 4-to-6 and possibly making up payloads */
935  switch (icmp->type)
936  {
939  break;
942  break;
945  {
946  struct GNUNET_TUN_IPv6Header *ipp =
947  (struct GNUNET_TUN_IPv6Header *) &icmp[1];
948  struct GNUNET_TUN_UdpHeader *udp =
949  (struct GNUNET_TUN_UdpHeader *) &ipp[1];
950 
951  if (mlen != 0)
952  {
953  /* sender did not strip ICMP payload? */
954  GNUNET_break_op (0);
955  return;
956  }
957  size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
958  GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
959  make_up_icmpv6_payload (ts, ipp, udp);
960  }
961  break;
964  {
965  struct GNUNET_TUN_IPv6Header *ipp =
966  (struct GNUNET_TUN_IPv6Header *) &icmp[1];
967  struct GNUNET_TUN_UdpHeader *udp =
968  (struct GNUNET_TUN_UdpHeader *) &ipp[1];
969 
970  if (mlen != 0)
971  {
972  /* sender did not strip ICMP payload? */
973  GNUNET_break_op (0);
974  return;
975  }
976  size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
977  GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
978  make_up_icmpv6_payload (ts, ipp, udp);
979  }
980  break;
983  stats,
984  gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
985  1,
986  GNUNET_NO);
987  return;
988  default:
989  GNUNET_break_op (0);
991  stats,
992  gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
993  1,
994  GNUNET_NO);
995  return;
996  }
997  /* end AF_INET */
998  break;
999  case AF_INET6:
1000  switch (icmp->type)
1001  {
1006  struct GNUNET_TUN_IPv6Header *ipp =
1007  (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1008  struct GNUNET_TUN_UdpHeader *udp =
1009  (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1010 
1011  if (mlen != 0)
1012  {
1013  /* sender did not strip ICMP payload? */
1014  GNUNET_break_op (0);
1015  return;
1016  }
1017  size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1018  GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1019  make_up_icmpv6_payload (ts, ipp, udp);
1020  }
1021  break;
1023  break;
1024  default:
1025  GNUNET_break_op (0);
1027  stats,
1028  gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1029  1,
1030  GNUNET_NO);
1031  return;
1032  }
1033  /* end AF_INET6 */
1034  break;
1035  default:
1036  GNUNET_break_op (0);
1037  return;
1038  }
1039  msg->size = htons (size);
1040  GNUNET_TUN_calculate_icmp_checksum (icmp, &i2v[1], mlen);
1041  (void) GNUNET_HELPER_send (helper_handle, msg, GNUNET_YES, NULL, NULL);
1042  }
1043  }
1044  break;
1045  default:
1046  GNUNET_assert (0);
1047  }
1049  GNUNET_TIME_absolute_get ().abs_value_us);
1051 }
1052 
1053 
1062 static int
1063 check_udp_back (void *cls, const struct GNUNET_EXIT_UdpReplyMessage *reply)
1064 {
1065  struct ChannelState *ts = cls;
1066 
1067  if (NULL == ts->heap_node)
1068  {
1069  GNUNET_break_op (0);
1070  return GNUNET_SYSERR;
1071  }
1072  if (AF_UNSPEC == ts->af)
1073  {
1074  GNUNET_break_op (0);
1075  return GNUNET_SYSERR;
1076  }
1077  return GNUNET_OK;
1078 }
1079 
1080 
1088 static void
1089 handle_udp_back (void *cls, const struct GNUNET_EXIT_UdpReplyMessage *reply)
1090 {
1091  struct ChannelState *ts = cls;
1092  size_t mlen;
1093 
1094  GNUNET_STATISTICS_update (stats,
1095  gettext_noop ("# UDP packets received from cadet"),
1096  1,
1097  GNUNET_NO);
1098  mlen =
1099  ntohs (reply->header.size) - sizeof (struct GNUNET_EXIT_UdpReplyMessage);
1100  {
1101  char sbuf[INET6_ADDRSTRLEN];
1102  char dbuf[INET6_ADDRSTRLEN];
1103 
1104  GNUNET_log (
1106  "Received UDP reply from cadet, sending %u bytes from [%s]:%u -> [%s]:%u via TUN\n",
1107  (unsigned int) mlen,
1108  inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1109  ts->destination_port,
1110  inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
1111  ts->source_port);
1112  }
1113  switch (ts->af)
1114  {
1115  case AF_INET: {
1116  size_t size = sizeof (struct GNUNET_TUN_IPv4Header) +
1117  sizeof (struct GNUNET_TUN_UdpHeader) +
1118  sizeof (struct GNUNET_MessageHeader) +
1119  sizeof (struct GNUNET_TUN_Layer2PacketHeader) + mlen;
1120  {
1121  char buf[size] GNUNET_ALIGN;
1122  struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1123  struct GNUNET_TUN_Layer2PacketHeader *tun =
1124  (struct GNUNET_TUN_Layer2PacketHeader *) &msg[1];
1125  struct GNUNET_TUN_IPv4Header *ipv4 =
1126  (struct GNUNET_TUN_IPv4Header *) &tun[1];
1127  struct GNUNET_TUN_UdpHeader *udp =
1128  (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
1129  msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1130  msg->size = htons (size);
1131  tun->flags = htons (0);
1132  tun->proto = htons (ETH_P_IPV4);
1134  IPPROTO_UDP,
1135  sizeof (struct GNUNET_TUN_UdpHeader) +
1136  mlen,
1137  &ts->destination_ip.v4,
1138  &ts->source_ip.v4);
1139  if (0 == ntohs (reply->source_port))
1140  udp->source_port = htons (ts->destination_port);
1141  else
1142  udp->source_port = reply->source_port;
1143  if (0 == ntohs (reply->destination_port))
1144  udp->destination_port = htons (ts->source_port);
1145  else
1146  udp->destination_port = reply->destination_port;
1147  udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
1148  GNUNET_TUN_calculate_udp4_checksum (ipv4, udp, &reply[1], mlen);
1149  GNUNET_memcpy (&udp[1], &reply[1], mlen);
1150  (void) GNUNET_HELPER_send (helper_handle, msg, GNUNET_YES, NULL, NULL);
1151  }
1152  }
1153  break;
1154  case AF_INET6: {
1155  size_t size = sizeof (struct GNUNET_TUN_IPv6Header) +
1156  sizeof (struct GNUNET_TUN_UdpHeader) +
1157  sizeof (struct GNUNET_MessageHeader) +
1158  sizeof (struct GNUNET_TUN_Layer2PacketHeader) + mlen;
1159  {
1160  char buf[size] GNUNET_ALIGN;
1161  struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1162  struct GNUNET_TUN_Layer2PacketHeader *tun =
1163  (struct GNUNET_TUN_Layer2PacketHeader *) &msg[1];
1164  struct GNUNET_TUN_IPv6Header *ipv6 =
1165  (struct GNUNET_TUN_IPv6Header *) &tun[1];
1166  struct GNUNET_TUN_UdpHeader *udp =
1167  (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
1168  msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1169  msg->size = htons (size);
1170  tun->flags = htons (0);
1171  tun->proto = htons (ETH_P_IPV6);
1173  IPPROTO_UDP,
1174  sizeof (struct GNUNET_TUN_UdpHeader) +
1175  mlen,
1176  &ts->destination_ip.v6,
1177  &ts->source_ip.v6);
1178  if (0 == ntohs (reply->source_port))
1179  udp->source_port = htons (ts->destination_port);
1180  else
1181  udp->source_port = reply->source_port;
1182  if (0 == ntohs (reply->destination_port))
1183  udp->destination_port = htons (ts->source_port);
1184  else
1185  udp->destination_port = reply->destination_port;
1186  udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
1187  GNUNET_TUN_calculate_udp6_checksum (ipv6, udp, &reply[1], mlen);
1188  GNUNET_memcpy (&udp[1], &reply[1], mlen);
1189  (void) GNUNET_HELPER_send (helper_handle, msg, GNUNET_YES, NULL, NULL);
1190  }
1191  }
1192  break;
1193  default:
1194  GNUNET_assert (0);
1195  }
1197  GNUNET_TIME_absolute_get ().abs_value_us);
1199 }
1200 
1201 
1210 static int
1212 {
1213  struct ChannelState *ts = cls;
1214 
1215  if (NULL == ts->heap_node)
1216  {
1217  GNUNET_break_op (0);
1218  return GNUNET_SYSERR;
1219  }
1220  if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1221  {
1222  GNUNET_break_op (0);
1223  return GNUNET_SYSERR;
1224  }
1225  return GNUNET_OK;
1226 }
1227 
1228 
1236 static void
1238 {
1239  struct ChannelState *ts = cls;
1240  size_t mlen;
1241 
1242  GNUNET_STATISTICS_update (stats,
1243  gettext_noop ("# TCP packets received from cadet"),
1244  1,
1245  GNUNET_NO);
1246  mlen = ntohs (data->header.size) - sizeof (struct GNUNET_EXIT_TcpDataMessage);
1247  {
1248  char sbuf[INET6_ADDRSTRLEN];
1249  char dbuf[INET6_ADDRSTRLEN];
1250 
1251  GNUNET_log (
1253  "Received TCP reply from cadet, sending %u bytes from [%s]:%u -> [%s]:%u via TUN\n",
1254  (unsigned int) mlen,
1255  inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1256  ts->destination_port,
1257  inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
1258  ts->source_port);
1259  }
1260  switch (ts->af)
1261  {
1262  case AF_INET: {
1263  size_t size = sizeof (struct GNUNET_TUN_IPv4Header) +
1264  sizeof (struct GNUNET_TUN_TcpHeader) +
1265  sizeof (struct GNUNET_MessageHeader) +
1266  sizeof (struct GNUNET_TUN_Layer2PacketHeader) + mlen;
1267  {
1268  char buf[size] GNUNET_ALIGN;
1269  struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1270  struct GNUNET_TUN_Layer2PacketHeader *tun =
1271  (struct GNUNET_TUN_Layer2PacketHeader *) &msg[1];
1272  struct GNUNET_TUN_IPv4Header *ipv4 =
1273  (struct GNUNET_TUN_IPv4Header *) &tun[1];
1274  struct GNUNET_TUN_TcpHeader *tcp =
1275  (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
1276  msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1277  msg->size = htons (size);
1278  tun->flags = htons (0);
1279  tun->proto = htons (ETH_P_IPV4);
1281  IPPROTO_TCP,
1282  sizeof (struct GNUNET_TUN_TcpHeader) +
1283  mlen,
1284  &ts->destination_ip.v4,
1285  &ts->source_ip.v4);
1286  *tcp = data->tcp_header;
1287  tcp->source_port = htons (ts->destination_port);
1288  tcp->destination_port = htons (ts->source_port);
1289  GNUNET_TUN_calculate_tcp4_checksum (ipv4, tcp, &data[1], mlen);
1290  GNUNET_memcpy (&tcp[1], &data[1], mlen);
1291  (void) GNUNET_HELPER_send (helper_handle, msg, GNUNET_YES, NULL, NULL);
1292  }
1293  }
1294  break;
1295  case AF_INET6: {
1296  size_t size = sizeof (struct GNUNET_TUN_IPv6Header) +
1297  sizeof (struct GNUNET_TUN_TcpHeader) +
1298  sizeof (struct GNUNET_MessageHeader) +
1299  sizeof (struct GNUNET_TUN_Layer2PacketHeader) + mlen;
1300  {
1301  char buf[size] GNUNET_ALIGN;
1302  struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1303  struct GNUNET_TUN_Layer2PacketHeader *tun =
1304  (struct GNUNET_TUN_Layer2PacketHeader *) &msg[1];
1305  struct GNUNET_TUN_IPv6Header *ipv6 =
1306  (struct GNUNET_TUN_IPv6Header *) &tun[1];
1307  struct GNUNET_TUN_TcpHeader *tcp =
1308  (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
1309  msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1310  msg->size = htons (size);
1311  tun->flags = htons (0);
1312  tun->proto = htons (ETH_P_IPV6);
1314  IPPROTO_TCP,
1315  sizeof (struct GNUNET_TUN_TcpHeader) +
1316  mlen,
1317  &ts->destination_ip.v6,
1318  &ts->source_ip.v6);
1319  *tcp = data->tcp_header;
1320  tcp->source_port = htons (ts->destination_port);
1321  tcp->destination_port = htons (ts->source_port);
1322  GNUNET_TUN_calculate_tcp6_checksum (ipv6, tcp, &data[1], mlen);
1323  GNUNET_memcpy (&tcp[1], &data[1], mlen);
1324  (void) GNUNET_HELPER_send (helper_handle, msg, GNUNET_YES, NULL, NULL);
1325  }
1326  }
1327  break;
1328  }
1330  GNUNET_TIME_absolute_get ().abs_value_us);
1332 }
1333 
1334 
1343 static struct GNUNET_CADET_Channel *
1345  const struct GNUNET_PeerIdentity *target,
1346  const struct GNUNET_HashCode *port)
1347 {
1348  struct GNUNET_MQ_MessageHandler cadet_handlers[] =
1349  {GNUNET_MQ_hd_var_size (udp_back,
1352  ts),
1353  GNUNET_MQ_hd_var_size (tcp_back,
1356  ts),
1357  GNUNET_MQ_hd_var_size (icmp_back,
1360  ts),
1362 
1363  return GNUNET_CADET_channel_create (cadet_handle,
1364  ts,
1365  target,
1366  port,
1367  NULL,
1368  &channel_cleaner,
1369  cadet_handlers);
1370 }
1371 
1372 
1383 static void
1385  const struct GNUNET_PeerIdentity *id,
1386  const struct GNUNET_PeerIdentity *get_path,
1387  unsigned int get_path_length,
1388  const struct GNUNET_PeerIdentity *put_path,
1389  unsigned int put_path_length)
1390 {
1391  struct ChannelState *ts = cls;
1392  struct GNUNET_HashCode port;
1393 
1395  "Exit %s found for destination %s!\n",
1396  GNUNET_i2s (id),
1399  ts->search = NULL;
1400  switch (ts->af)
1401  {
1402  case AF_INET:
1403  /* these must match the strings used in gnunet-daemon-exit */
1406  &port);
1407  break;
1408  case AF_INET6:
1409  /* these must match the strings used in gnunet-daemon-exit */
1412  &port);
1413  break;
1414  default:
1415  GNUNET_break (0);
1416  return;
1417  }
1419  "Creating tunnel to %s for destination %s!\n",
1420  GNUNET_i2s (id),
1422  ts->channel = create_channel (ts, id, &port);
1423 }
1424 
1425 
1433 static struct ChannelState *
1435 {
1436  struct ChannelState *ts;
1437 
1438  GNUNET_STATISTICS_update (stats,
1439  gettext_noop ("# Cadet channels created"),
1440  1,
1441  GNUNET_NO);
1442  ts = GNUNET_new (struct ChannelState);
1443  ts->af = client_af;
1444  ts->destination = *dt->destination;
1445  ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
1447  if (dt->destination->is_service)
1448  {
1449  struct GNUNET_HashCode cadet_port;
1450 
1453  .service_descriptor,
1454  ts->destination_port,
1455  &cadet_port);
1456  ts->channel =
1457  create_channel (ts,
1459  &cadet_port);
1460 
1461  if (NULL == ts->channel)
1462  {
1463  GNUNET_break (0);
1464  GNUNET_free (ts);
1465  return NULL;
1466  }
1468  "Creating channel to peer %s offering service %s on port %u\n",
1469  GNUNET_i2s (
1470  &dt->destination->details.service_destination.target),
1472  .service_descriptor),
1473  (unsigned int) ts->destination_port);
1474  }
1475  else
1476  {
1477  char *policy;
1478 
1479  switch (dt->destination->details.exit_destination.af)
1480  {
1481  case AF_INET: {
1483 
1485  .ip.v4,
1486  dt->destination_port,
1487  address);
1488  GNUNET_asprintf (&policy,
1489  "%s%s",
1491  address);
1492  break;
1493  }
1494  case AF_INET6: {
1496 
1498  .ip.v6,
1499  dt->destination_port,
1500  address);
1501  GNUNET_asprintf (&policy,
1502  "%s%s",
1504  address);
1505  break;
1506  }
1507  default:
1508  GNUNET_assert (0);
1509  break;
1510  }
1511 
1513  "Requesting connect by string: %s\n",
1514  policy);
1515  ts->search = GNUNET_REGEX_search (cfg, policy, &handle_regex_result, ts);
1516  GNUNET_free (policy);
1517  }
1518  return ts;
1519 }
1520 
1521 
1527 static void
1529 {
1530  struct ChannelState *ts;
1531 
1532  ts = GNUNET_CONTAINER_heap_peek (channel_heap);
1533  GNUNET_assert (NULL != ts);
1534  if (except == ts)
1535  return; /* can't do this */
1537  "Tearing down expired channel to %s\n",
1539  free_channel_state (ts);
1540 }
1541 
1542 
1554 static void
1556  int af,
1557  uint8_t protocol,
1558  const void *source_ip,
1559  const void *destination_ip,
1560  const void *payload,
1561  size_t payload_length)
1562 {
1563  struct GNUNET_HashCode key;
1564  struct ChannelState *ts;
1565  size_t alen;
1566  size_t mlen;
1567  struct GNUNET_MQ_Envelope *env;
1568  const struct GNUNET_TUN_UdpHeader *udp;
1569  const struct GNUNET_TUN_TcpHeader *tcp;
1570  const struct GNUNET_TUN_IcmpHeader *icmp;
1571  struct DestinationChannel *dt;
1572  uint16_t source_port;
1573  uint16_t destination_port;
1574 
1575  switch (protocol)
1576  {
1577  case IPPROTO_UDP: {
1578  if (payload_length < sizeof (struct GNUNET_TUN_UdpHeader))
1579  {
1580  /* blame kernel? */
1581  GNUNET_break (0);
1582  return;
1583  }
1584  tcp = NULL; /* make compiler happy */
1585  icmp = NULL; /* make compiler happy */
1586  udp = payload;
1587  if (udp->len < sizeof (struct GNUNET_TUN_UdpHeader))
1588  {
1589  GNUNET_break_op (0);
1590  return;
1591  }
1592  source_port = ntohs (udp->source_port);
1593  destination_port = ntohs (udp->destination_port);
1595  IPPROTO_UDP,
1596  source_ip,
1597  source_port,
1598  destination_ip,
1599  destination_port,
1600  &key);
1601  }
1602  break;
1603  case IPPROTO_TCP: {
1604  if (payload_length < sizeof (struct GNUNET_TUN_TcpHeader))
1605  {
1606  /* blame kernel? */
1607  GNUNET_break (0);
1608  return;
1609  }
1610  udp = NULL; /* make compiler happy */
1611  icmp = NULL; /* make compiler happy */
1612  tcp = payload;
1613  if (tcp->off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1614  {
1615  GNUNET_break_op (0);
1616  return;
1617  }
1618  source_port = ntohs (tcp->source_port);
1619  destination_port = ntohs (tcp->destination_port);
1621  IPPROTO_TCP,
1622  source_ip,
1623  source_port,
1624  destination_ip,
1625  destination_port,
1626  &key);
1627  }
1628  break;
1629  case IPPROTO_ICMP:
1630  case IPPROTO_ICMPV6: {
1631  if ((AF_INET == af) ^ (protocol == IPPROTO_ICMP))
1632  {
1633  GNUNET_break (0);
1634  return;
1635  }
1636  if (payload_length < sizeof (struct GNUNET_TUN_IcmpHeader))
1637  {
1638  /* blame kernel? */
1639  GNUNET_break (0);
1640  return;
1641  }
1642  tcp = NULL; /* make compiler happy */
1643  udp = NULL; /* make compiler happy */
1644  icmp = payload;
1645  source_port = 0;
1646  destination_port = 0;
1648  protocol,
1649  source_ip,
1650  0,
1651  destination_ip,
1652  0,
1653  &key);
1654  }
1655  break;
1656  default:
1658  _ ("Protocol %u not supported, dropping\n"),
1659  (unsigned int) protocol);
1660  return;
1661  }
1662  alen = 0;
1663  if (! destination->is_service)
1664  {
1665  switch (destination->details.exit_destination.af)
1666  {
1667  case AF_INET:
1668  alen = sizeof (struct in_addr);
1669  break;
1670  case AF_INET6:
1671  alen = sizeof (struct in6_addr);
1672  break;
1673  default:
1674  GNUNET_assert (0);
1675  }
1676 
1677  {
1678  char sbuf[INET6_ADDRSTRLEN];
1679  char dbuf[INET6_ADDRSTRLEN];
1680  char xbuf[INET6_ADDRSTRLEN];
1681 
1682  GNUNET_log (
1684  "Routing %s packet from [%s]:%u -> [%s]:%u to destination [%s]:%u\n",
1685  (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1686  inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1687  source_port,
1688  inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1689  destination_port,
1690  inet_ntop (destination->details.exit_destination.af,
1691  &destination->details.exit_destination.ip,
1692  xbuf,
1693  sizeof (xbuf)),
1694  destination_port);
1695  }
1696  for (dt = destination->dt_head; NULL != dt; dt = dt->next)
1697  if (dt->destination_port == destination_port)
1698  break;
1699  }
1700  else
1701  {
1702  {
1703  char sbuf[INET6_ADDRSTRLEN];
1704  char dbuf[INET6_ADDRSTRLEN];
1705 
1706  GNUNET_log (
1708  "Routing %s packet from [%s]:%u -> [%s]:%u to service %s at peer %s\n",
1709  (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1710  inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1711  source_port,
1712  inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1713  destination_port,
1714  GNUNET_h2s (
1715  &destination->details.service_destination.service_descriptor),
1716  GNUNET_i2s (&destination->details.service_destination.target));
1717  }
1718  for (dt = destination->dt_head; NULL != dt; dt = dt->next)
1719  if (dt->destination_port == destination_port)
1720  break;
1721  }
1722  if (NULL == dt)
1723  {
1724  dt = GNUNET_new (struct DestinationChannel);
1725  dt->destination = destination;
1726  GNUNET_CONTAINER_DLL_insert (destination->dt_head,
1727  destination->dt_tail,
1728  dt);
1730  }
1731 
1732  /* see if we have an existing channel for this destination */
1733  ts = GNUNET_CONTAINER_multihashmap_get (channel_map, &key);
1734  if (NULL == ts)
1735  {
1737  "Creating new channel for key %s\n",
1738  GNUNET_h2s (&key));
1739  /* need to either use the existing channel from the destination (if still
1740  available) or create a fresh one */
1741  ts = create_channel_to_destination (dt, af);
1742  if (NULL == ts)
1743  return;
1744  /* now bind existing "unbound" channel to our IP/port tuple */
1745  ts->protocol = protocol;
1746  ts->af = af;
1747  if (AF_INET == af)
1748  {
1749  ts->source_ip.v4 = *(const struct in_addr *) source_ip;
1750  ts->destination_ip.v4 = *(const struct in_addr *) destination_ip;
1751  }
1752  else
1753  {
1754  ts->source_ip.v6 = *(const struct in6_addr *) source_ip;
1755  ts->destination_ip.v6 = *(const struct in6_addr *) destination_ip;
1756  }
1757  ts->source_port = source_port;
1759  ts->heap_node =
1760  GNUNET_CONTAINER_heap_insert (channel_heap,
1761  ts,
1762  GNUNET_TIME_absolute_get ().abs_value_us);
1765  channel_map,
1766  &key,
1767  ts,
1769  GNUNET_STATISTICS_update (stats,
1770  gettext_noop ("# Active channels"),
1771  1,
1772  GNUNET_NO);
1773  while (GNUNET_CONTAINER_multihashmap_size (channel_map) >
1775  expire_channel (ts);
1776  }
1777  else
1778  {
1781  .abs_value_us);
1782  }
1783  if (NULL == ts->channel)
1784  {
1786  "Packet dropped, channel to %s not yet ready (%s)\n",
1788  (NULL == ts->search) ? "EXIT search failed"
1789  : "EXIT search active");
1790  GNUNET_STATISTICS_update (stats,
1791  gettext_noop (
1792  "# Packets dropped (channel not yet online)"),
1793  1,
1794  GNUNET_NO);
1795  return;
1796  }
1797 
1798  /* send via channel */
1799  switch (protocol)
1800  {
1801  case IPPROTO_UDP:
1802  if (destination->is_service)
1803  {
1804  struct GNUNET_EXIT_UdpServiceMessage *usm;
1805 
1806  mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) + payload_length -
1807  sizeof (struct GNUNET_TUN_UdpHeader);
1808  if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
1809  {
1810  GNUNET_break (0);
1811  return;
1812  }
1813  env = GNUNET_MQ_msg_extra (usm,
1814  payload_length -
1815  sizeof (struct GNUNET_TUN_UdpHeader),
1817  /* if the source port is below 32000, we assume it has a special
1818  meaning; if not, we pick a random port (this is a heuristic) */
1819  usm->source_port =
1820  (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1821  usm->destination_port = udp->destination_port;
1822  GNUNET_memcpy (&usm[1],
1823  &udp[1],
1824  payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1825  }
1826  else
1827  {
1828  struct GNUNET_EXIT_UdpInternetMessage *uim;
1829  struct in_addr *ip4dst;
1830  struct in6_addr *ip6dst;
1831  void *payload;
1832 
1833  mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) + alen +
1834  payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1835  if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
1836  {
1837  GNUNET_break (0);
1838  return;
1839  }
1840  env = GNUNET_MQ_msg_extra (uim,
1841  payload_length + alen -
1842  sizeof (struct GNUNET_TUN_UdpHeader),
1844  uim->af = htonl (destination->details.exit_destination.af);
1845  uim->source_port =
1846  (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1847  uim->destination_port = udp->destination_port;
1848  switch (destination->details.exit_destination.af)
1849  {
1850  case AF_INET:
1851  ip4dst = (struct in_addr *) &uim[1];
1852  *ip4dst = destination->details.exit_destination.ip.v4;
1853  payload = &ip4dst[1];
1854  break;
1855  case AF_INET6:
1856  ip6dst = (struct in6_addr *) &uim[1];
1857  *ip6dst = destination->details.exit_destination.ip.v6;
1858  payload = &ip6dst[1];
1859  break;
1860  default:
1861  GNUNET_assert (0);
1862  }
1863  GNUNET_memcpy (payload,
1864  &udp[1],
1865  payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1866  }
1867  break;
1868  case IPPROTO_TCP:
1869  if (GNUNET_NO == ts->is_established)
1870  {
1871  if (destination->is_service)
1872  {
1874 
1875  mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
1876  payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1877  if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
1878  {
1879  GNUNET_break (0);
1880  return;
1881  }
1882  env =
1883  GNUNET_MQ_msg_extra (tsm,
1884  payload_length -
1885  sizeof (struct GNUNET_TUN_TcpHeader),
1887  tsm->reserved = htonl (0);
1888  tsm->tcp_header = *tcp;
1889  GNUNET_memcpy (&tsm[1],
1890  &tcp[1],
1891  payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1892  }
1893  else
1894  {
1896  struct in_addr *ip4dst;
1897  struct in6_addr *ip6dst;
1898  void *payload;
1899 
1900  mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) + alen +
1901  payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1902  if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
1903  {
1904  GNUNET_break (0);
1905  return;
1906  }
1907  env =
1908  GNUNET_MQ_msg_extra (tim,
1909  payload_length + alen -
1910  sizeof (struct GNUNET_TUN_TcpHeader),
1912  tim->af = htonl (destination->details.exit_destination.af);
1913  tim->tcp_header = *tcp;
1914  switch (destination->details.exit_destination.af)
1915  {
1916  case AF_INET:
1917  ip4dst = (struct in_addr *) &tim[1];
1918  *ip4dst = destination->details.exit_destination.ip.v4;
1919  payload = &ip4dst[1];
1920  break;
1921  case AF_INET6:
1922  ip6dst = (struct in6_addr *) &tim[1];
1923  *ip6dst = destination->details.exit_destination.ip.v6;
1924  payload = &ip6dst[1];
1925  break;
1926  default:
1927  GNUNET_assert (0);
1928  }
1929  GNUNET_memcpy (payload,
1930  &tcp[1],
1931  payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1932  }
1933  }
1934  else
1935  {
1936  struct GNUNET_EXIT_TcpDataMessage *tdm;
1937 
1938  mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) + payload_length -
1939  sizeof (struct GNUNET_TUN_TcpHeader);
1940  if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
1941  {
1942  GNUNET_break (0);
1943  return;
1944  }
1945  env = GNUNET_MQ_msg_extra (tdm,
1946  payload_length -
1947  sizeof (struct GNUNET_TUN_TcpHeader),
1949  tdm->reserved = htonl (0);
1950  tdm->tcp_header = *tcp;
1951  GNUNET_memcpy (&tdm[1],
1952  &tcp[1],
1953  payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1954  }
1955  break;
1956  case IPPROTO_ICMP:
1957  case IPPROTO_ICMPV6:
1958  if (destination->is_service)
1959  {
1960  struct GNUNET_EXIT_IcmpServiceMessage *ism;
1961 
1962  /* ICMP protocol translation will be done by the receiver (as we don't know
1963  the target AF); however, we still need to possibly discard the payload
1964  depending on the ICMP type */
1965  switch (af)
1966  {
1967  case AF_INET:
1968  switch (icmp->type)
1969  {
1972  break;
1976  /* throw away ICMP payload, won't be useful for the other side anyway */
1977  payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1978  break;
1979  default:
1980  GNUNET_STATISTICS_update (stats,
1981  gettext_noop (
1982  "# ICMPv4 packets dropped (not allowed)"),
1983  1,
1984  GNUNET_NO);
1985  return;
1986  }
1987  /* end of AF_INET */
1988  break;
1989  case AF_INET6:
1990  switch (icmp->type)
1991  {
1996  /* throw away ICMP payload, won't be useful for the other side anyway */
1997  payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1998  break;
2001  break;
2002  default:
2003  GNUNET_STATISTICS_update (stats,
2004  gettext_noop (
2005  "# ICMPv6 packets dropped (not allowed)"),
2006  1,
2007  GNUNET_NO);
2008  return;
2009  }
2010  /* end of AF_INET6 */
2011  break;
2012  default:
2013  GNUNET_assert (0);
2014  break;
2015  }
2016 
2017  /* update length calculations, as payload_length may have changed */
2018  mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) + alen +
2019  payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
2020  if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
2021  {
2022  GNUNET_break (0);
2023  return;
2024  }
2025 
2026  env = GNUNET_MQ_msg_extra (ism,
2027  payload_length -
2028  sizeof (struct GNUNET_TUN_IcmpHeader),
2030  ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
2031  ism->icmp_header = *icmp;
2032  GNUNET_memcpy (&ism[1],
2033  &icmp[1],
2034  payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
2035  }
2036  else
2037  {
2038  struct GNUNET_EXIT_IcmpInternetMessage *iim;
2039  struct in_addr *ip4dst;
2040  struct in6_addr *ip6dst;
2041  void *payload;
2042  uint8_t new_type;
2043 
2044  new_type = icmp->type;
2045  /* Perform ICMP protocol-translation (depending on destination AF and source AF)
2046  and throw away ICMP payload depending on ICMP message type */
2047  switch (af)
2048  {
2049  case AF_INET:
2050  switch (icmp->type)
2051  {
2053  if (destination->details.exit_destination.af == AF_INET6)
2055  break;
2057  if (destination->details.exit_destination.af == AF_INET6)
2059  break;
2061  if (destination->details.exit_destination.af == AF_INET6)
2063  /* throw away IP-payload, exit will have to make it up anyway */
2064  payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2065  break;
2067  if (destination->details.exit_destination.af == AF_INET6)
2069  /* throw away IP-payload, exit will have to make it up anyway */
2070  payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2071  break;
2073  if (destination->details.exit_destination.af == AF_INET6)
2074  {
2076  stats,
2077  gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
2078  1,
2079  GNUNET_NO);
2080  return;
2081  }
2082  /* throw away IP-payload, exit will have to make it up anyway */
2083  payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2084  break;
2085  default:
2087  stats,
2088  gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2089  1,
2090  GNUNET_NO);
2091  return;
2092  }
2093  /* end of AF_INET */
2094  break;
2095  case AF_INET6:
2096  switch (icmp->type)
2097  {
2099  if (destination->details.exit_destination.af == AF_INET)
2101  /* throw away IP-payload, exit will have to make it up anyway */
2102  payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2103  break;
2105  if (destination->details.exit_destination.af == AF_INET)
2107  /* throw away IP-payload, exit will have to make it up anyway */
2108  payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2109  break;
2111  if (destination->details.exit_destination.af == AF_INET)
2112  {
2114  stats,
2115  gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2116  1,
2117  GNUNET_NO);
2118  return;
2119  }
2120  /* throw away IP-payload, exit will have to make it up anyway */
2121  payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2122  break;
2124  if (destination->details.exit_destination.af == AF_INET)
2125  {
2127  stats,
2128  gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2129  1,
2130  GNUNET_NO);
2131  return;
2132  }
2133  /* throw away IP-payload, exit will have to make it up anyway */
2134  payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2135  break;
2137  if (destination->details.exit_destination.af == AF_INET)
2139  break;
2141  if (destination->details.exit_destination.af == AF_INET)
2142  new_type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
2143  break;
2144  default:
2146  stats,
2147  gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2148  1,
2149  GNUNET_NO);
2150  return;
2151  }
2152  /* end of AF_INET6 */
2153  break;
2154  default:
2155  GNUNET_assert (0);
2156  }
2157 
2158  /* update length calculations, as payload_length may have changed */
2159  mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) + alen +
2160  payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
2161  if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
2162  {
2163  GNUNET_break (0);
2164  return;
2165  }
2166  env = GNUNET_MQ_msg_extra (iim,
2167  alen + payload_length -
2168  sizeof (struct GNUNET_TUN_IcmpHeader),
2170  iim->icmp_header = *icmp;
2171  iim->icmp_header.type = new_type;
2172  iim->af = htonl (destination->details.exit_destination.af);
2173  switch (destination->details.exit_destination.af)
2174  {
2175  case AF_INET:
2176  ip4dst = (struct in_addr *) &iim[1];
2177  *ip4dst = destination->details.exit_destination.ip.v4;
2178  payload = &ip4dst[1];
2179  break;
2180  case AF_INET6:
2181  ip6dst = (struct in6_addr *) &iim[1];
2182  *ip6dst = destination->details.exit_destination.ip.v6;
2183  payload = &ip6dst[1];
2184  break;
2185  default:
2186  GNUNET_assert (0);
2187  }
2188  GNUNET_memcpy (payload,
2189  &icmp[1],
2190  payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
2191  }
2192  break;
2193  default:
2194  /* not supported above, how can we get here !? */
2195  GNUNET_assert (0);
2196  break;
2197  }
2198  ts->is_established = GNUNET_YES;
2199  send_to_channel (ts, env);
2200 }
2201 
2202 
2215 static int
2216 message_token (void *cls, const struct GNUNET_MessageHeader *message)
2217 {
2218  const struct GNUNET_TUN_Layer2PacketHeader *tun;
2219  size_t mlen;
2220  struct GNUNET_HashCode key;
2221  struct DestinationEntry *de;
2222 
2223  GNUNET_STATISTICS_update (stats,
2224  gettext_noop (
2225  "# Packets received from TUN interface"),
2226  1,
2227  GNUNET_NO);
2228  mlen = ntohs (message->size);
2229  if ((ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
2230  (mlen < sizeof (struct GNUNET_MessageHeader) +
2231  sizeof (struct GNUNET_TUN_Layer2PacketHeader)))
2232  {
2233  GNUNET_break (0);
2234  return GNUNET_OK;
2235  }
2236  tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
2237  mlen -= (sizeof (struct GNUNET_MessageHeader) +
2238  sizeof (struct GNUNET_TUN_Layer2PacketHeader));
2239  switch (ntohs (tun->proto))
2240  {
2241  case ETH_P_IPV6: {
2242  const struct GNUNET_TUN_IPv6Header *pkt6;
2243 
2244  if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
2245  {
2246  /* blame kernel */
2247  GNUNET_break (0);
2248  return GNUNET_OK;
2249  }
2250  pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
2251  get_destination_key_from_ip (AF_INET6, &pkt6->destination_address, &key);
2252  de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
2253  if (NULL == de)
2254  {
2255  char buf[INET6_ADDRSTRLEN];
2256 
2257  GNUNET_log (
2259  _ ("Packet received for unmapped destination `%s' (dropping it)\n"),
2260  inet_ntop (AF_INET6, &pkt6->destination_address, buf, sizeof (buf)));
2261  return GNUNET_OK;
2262  }
2263  route_packet (de,
2264  AF_INET6,
2265  pkt6->next_header,
2266  &pkt6->source_address,
2267  &pkt6->destination_address,
2268  &pkt6[1],
2269  mlen - sizeof (struct GNUNET_TUN_IPv6Header));
2270  }
2271  break;
2272  case ETH_P_IPV4: {
2273  struct GNUNET_TUN_IPv4Header *pkt4;
2274 
2275  if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
2276  {
2277  /* blame kernel */
2278  GNUNET_break (0);
2279  return GNUNET_OK;
2280  }
2281  pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2282  get_destination_key_from_ip (AF_INET, &pkt4->destination_address, &key);
2283  de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
2284  if (NULL == de)
2285  {
2286  char buf[INET_ADDRSTRLEN];
2287 
2288  GNUNET_log (
2290  _ ("Packet received for unmapped destination `%s' (dropping it)\n"),
2291  inet_ntop (AF_INET, &pkt4->destination_address, buf, sizeof (buf)));
2292  return GNUNET_OK;
2293  }
2294  if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
2295  {
2297  _ ("Received IPv4 packet with options (dropping it)\n"));
2298  return GNUNET_OK;
2299  }
2300  route_packet (de,
2301  AF_INET,
2302  pkt4->protocol,
2303  &pkt4->source_address,
2304  &pkt4->destination_address,
2305  &pkt4[1],
2306  mlen - sizeof (struct GNUNET_TUN_IPv4Header));
2307  }
2308  break;
2309  default:
2310  GNUNET_log (
2312  _ ("Received packet of unknown protocol %d from TUN (dropping it)\n"),
2313  (unsigned int) ntohs (tun->proto));
2314  break;
2315  }
2316  return GNUNET_OK;
2317 }
2318 
2319 
2328 static int
2329 allocate_v4_address (struct in_addr *v4)
2330 {
2331  const char *ipv4addr = vpn_argv[4];
2332  const char *ipv4mask = vpn_argv[5];
2333  struct in_addr addr;
2334  struct in_addr mask;
2335  struct in_addr rnd;
2336  struct GNUNET_HashCode key;
2337  unsigned int tries;
2338 
2339  GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2340  GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2341  /* Given 192.168.0.1/255.255.0.0, we want a mask
2342  of '192.168.255.255', thus: */
2343  mask.s_addr = addr.s_addr | ~mask.s_addr;
2344  tries = 0;
2345  do
2346  {
2347  tries++;
2348  if (tries > 16)
2349  {
2351  _ (
2352  "Failed to find unallocated IPv4 address in VPN's range\n"));
2353  return GNUNET_SYSERR;
2354  }
2355  /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2356  rnd.s_addr =
2358  v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2359  get_destination_key_from_ip (AF_INET, v4, &key);
2360  } while ((GNUNET_YES ==
2361  GNUNET_CONTAINER_multihashmap_contains (destination_map, &key)) ||
2362  (v4->s_addr == addr.s_addr) || (v4->s_addr == mask.s_addr));
2363  return GNUNET_OK;
2364 }
2365 
2366 
2375 static int
2376 allocate_v6_address (struct in6_addr *v6)
2377 {
2378  const char *ipv6addr = vpn_argv[2];
2379  struct in6_addr addr;
2380  struct in6_addr mask;
2381  struct in6_addr rnd;
2382  int i;
2383  struct GNUNET_HashCode key;
2384  unsigned int tries;
2385 
2386  GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2387  GNUNET_assert (ipv6prefix < 128);
2388  /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2389  thus: */
2390  mask = addr;
2391  for (i = 127; i >= ipv6prefix; i--)
2392  mask.s6_addr[i / 8] |= (1 << (i % 8));
2393 
2394  /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2395  tries = 0;
2396  do
2397  {
2398  tries++;
2399  if (tries > 16)
2400  {
2402  _ (
2403  "Failed to find unallocated IPv6 address in VPN's range\n"));
2404  return GNUNET_SYSERR;
2405  }
2406  for (i = 0; i < 16; i++)
2407  {
2408  rnd.s6_addr[i] =
2410  256);
2411  v6->s6_addr[i] = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2412  }
2413  get_destination_key_from_ip (AF_INET6, v6, &key);
2414  } while ((GNUNET_YES ==
2415  GNUNET_CONTAINER_multihashmap_contains (destination_map, &key)) ||
2416  (0 == GNUNET_memcmp (v6, &addr)) ||
2417  (0 == GNUNET_memcmp (v6, &mask)));
2418  return GNUNET_OK;
2419 }
2420 
2421 
2427 static void
2429 {
2430  struct DestinationChannel *dt;
2431 
2433  "Cleaning up destination entry `%s'\n",
2435  GNUNET_STATISTICS_update (stats,
2436  gettext_noop ("# Active destinations"),
2437  -1,
2438  GNUNET_NO);
2439  while (NULL != (dt = de->dt_head))
2440  {
2442  GNUNET_free (dt);
2443  }
2444  if (NULL != de->heap_node)
2445  {
2447  de->heap_node = NULL;
2448  GNUNET_assert (
2449  GNUNET_YES ==
2450  GNUNET_CONTAINER_multihashmap_remove (destination_map, &de->key, de));
2451  }
2452  GNUNET_free (de);
2453 }
2454 
2455 
2461 static void
2463 {
2464  struct DestinationEntry *de;
2465 
2466  de = GNUNET_CONTAINER_heap_peek (destination_heap);
2467  GNUNET_assert (NULL != de);
2468  if (except == de)
2469  return; /* can't do this */
2471 }
2472 
2473 
2488 static int
2489 allocate_response_ip (int *result_af,
2490  void **addr,
2491  struct in_addr *v4,
2492  struct in6_addr *v6)
2493 {
2494  *addr = NULL;
2495  switch (*result_af)
2496  {
2497  case AF_INET:
2498  if (GNUNET_OK != allocate_v4_address (v4))
2499  *result_af = AF_UNSPEC;
2500  else
2501  *addr = v4;
2502  break;
2503  case AF_INET6:
2504  if (GNUNET_OK != allocate_v6_address (v6))
2505  *result_af = AF_UNSPEC;
2506  else
2507  *addr = v6;
2508  break;
2509  case AF_UNSPEC:
2510  if (GNUNET_OK == allocate_v4_address (v4))
2511  {
2512  *addr = v4;
2513  *result_af = AF_INET;
2514  }
2515  else if (GNUNET_OK == allocate_v6_address (v6))
2516  {
2517  *addr = v6;
2518  *result_af = AF_INET6;
2519  }
2520  break;
2521  default:
2522  GNUNET_break (0);
2523  return GNUNET_SYSERR;
2524  }
2525  return GNUNET_OK;
2526 }
2527 
2528 
2538 static int
2540  const struct RedirectToIpRequestMessage *msg)
2541 {
2542  size_t alen;
2543  int addr_af;
2544 
2545  alen = ntohs (msg->header.size) - sizeof (struct RedirectToIpRequestMessage);
2546  addr_af = (int) htonl (msg->addr_af);
2547  switch (addr_af)
2548  {
2549  case AF_INET:
2550  if (alen != sizeof (struct in_addr))
2551  {
2552  GNUNET_break (0);
2553  return GNUNET_SYSERR;
2554  }
2555  break;
2556  case AF_INET6:
2557  if (alen != sizeof (struct in6_addr))
2558  {
2559  GNUNET_break (0);
2560  return GNUNET_SYSERR;
2561  }
2562  break;
2563  default:
2564  GNUNET_break (0);
2565  return GNUNET_SYSERR;
2566  }
2567  return GNUNET_OK;
2568 }
2569 
2570 
2579 static void
2581  const struct RedirectToIpRequestMessage *msg)
2582 {
2583  struct GNUNET_SERVICE_Client *client = cls;
2584  size_t alen;
2585  int addr_af;
2586  int result_af;
2587  struct in_addr v4;
2588  struct in6_addr v6;
2589  void *addr;
2590  struct DestinationEntry *de;
2591  struct GNUNET_HashCode key;
2592 
2593  alen = ntohs (msg->header.size) - sizeof (struct RedirectToIpRequestMessage);
2594  addr_af = (int) htonl (msg->addr_af);
2595  /* allocate response IP */
2596  result_af = (int) htonl (msg->result_af);
2597  if (GNUNET_OK != allocate_response_ip (&result_af, &addr, &v4, &v6))
2598  {
2599  GNUNET_SERVICE_client_drop (client);
2600  return;
2601  }
2602  /* send reply with our IP address */
2603  send_client_reply (client, msg->request_id, result_af, addr);
2604  if (result_af == AF_UNSPEC)
2605  {
2606  /* failure, we're done */
2608  return;
2609  }
2610 
2611  {
2612  char sbuf[INET6_ADDRSTRLEN];
2613  char dbuf[INET6_ADDRSTRLEN];
2614 
2616  "Allocated address %s for redirection via exit to %s\n",
2617  inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2618  inet_ntop (addr_af, &msg[1], dbuf, sizeof (dbuf)));
2619  }
2620 
2621  /* setup destination record */
2622  de = GNUNET_new (struct DestinationEntry);
2623  de->is_service = GNUNET_NO;
2624  de->details.exit_destination.af = addr_af;
2625  GNUNET_memcpy (&de->details.exit_destination.ip, &msg[1], alen);
2626  get_destination_key_from_ip (result_af, addr, &key);
2627  de->key = key;
2629  destination_map,
2630  &key,
2631  de,
2633  de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2634  de,
2636  msg->expiration_time)
2637  .abs_value_us);
2638  GNUNET_STATISTICS_update (stats,
2639  gettext_noop ("# Active destinations"),
2640  1,
2641  GNUNET_NO);
2642  while (GNUNET_CONTAINER_multihashmap_size (destination_map) >
2644  expire_destination (de);
2646 }
2647 
2648 
2657 static void
2659  void *cls,
2660  const struct RedirectToServiceRequestMessage *msg)
2661 {
2662  struct GNUNET_SERVICE_Client *client = cls;
2663  int result_af;
2664  struct in_addr v4;
2665  struct in6_addr v6;
2666  void *addr;
2667  struct DestinationEntry *de;
2668  struct GNUNET_HashCode key;
2669  struct DestinationChannel *dt;
2670 
2671  /* allocate response IP */
2672  result_af = (int) htonl (msg->result_af);
2673  if (GNUNET_OK != allocate_response_ip (&result_af, &addr, &v4, &v6))
2674  {
2675  GNUNET_break (0);
2676  GNUNET_SERVICE_client_drop (client);
2677  return;
2678  }
2679  send_client_reply (client, msg->request_id, result_af, addr);
2680  if (result_af == AF_UNSPEC)
2681  {
2682  /* failure, we're done */
2684  _ ("Failed to allocate IP address for new destination\n"));
2686  return;
2687  }
2688 
2689  {
2690  char sbuf[INET6_ADDRSTRLEN];
2691 
2693  "Allocated address %s for redirection to service %s on peer %s\n",
2694  inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2696  GNUNET_i2s (&msg->target));
2697  }
2698 
2699  /* setup destination record */
2700  de = GNUNET_new (struct DestinationEntry);
2701  de->is_service = GNUNET_YES;
2702  de->details.service_destination.target = msg->target;
2703  de->details.service_destination.service_descriptor = msg->service_descriptor;
2704  get_destination_key_from_ip (result_af, addr, &key);
2705  de->key = key;
2707  destination_map,
2708  &key,
2709  de,
2711  de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2712  de,
2714  msg->expiration_time)
2715  .abs_value_us);
2716  while (GNUNET_CONTAINER_multihashmap_size (destination_map) >
2718  expire_destination (de);
2719 
2720  dt = GNUNET_new (struct DestinationChannel);
2721  dt->destination = de;
2723  /* we're done */
2725 }
2726 
2727 
2736 static int
2737 cleanup_destination (void *cls, const struct GNUNET_HashCode *key, void *value)
2738 {
2739  struct DestinationEntry *de = value;
2740 
2742  return GNUNET_OK;
2743 }
2744 
2745 
2754 static int
2755 cleanup_channel (void *cls, const struct GNUNET_HashCode *key, void *value)
2756 {
2757  struct ChannelState *ts = value;
2758 
2760  "Tearing down channel to `%s' during cleanup\n",
2762  free_channel_state (ts);
2763  return GNUNET_OK;
2764 }
2765 
2766 
2772 static void
2773 cleanup (void *cls)
2774 {
2775  unsigned int i;
2776 
2777  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "VPN is shutting down\n");
2778  if (NULL != destination_map)
2779  {
2780  GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2782  NULL);
2783  GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2784  destination_map = NULL;
2785  }
2786  if (NULL != destination_heap)
2787  {
2788  GNUNET_CONTAINER_heap_destroy (destination_heap);
2789  destination_heap = NULL;
2790  }
2791  if (NULL != channel_map)
2792  {
2795  channel_map = NULL;
2796  }
2797  if (NULL != channel_heap)
2798  {
2799  GNUNET_CONTAINER_heap_destroy (channel_heap);
2800  channel_heap = NULL;
2801  }
2802  if (NULL != cadet_handle)
2803  {
2804  GNUNET_CADET_disconnect (cadet_handle);
2805  cadet_handle = NULL;
2806  }
2807  if (NULL != helper_handle)
2808  {
2809  GNUNET_HELPER_kill (helper_handle, GNUNET_NO);
2810  GNUNET_HELPER_wait (helper_handle);
2811  helper_handle = NULL;
2812  }
2813  if (NULL != stats)
2814  {
2816  stats = NULL;
2817  }
2818  for (i = 0; i < 5; i++)
2820 }
2821 
2822 
2831 static void *
2833  struct GNUNET_SERVICE_Client *c,
2834  struct GNUNET_MQ_Handle *mq)
2835 {
2836  return c;
2837 }
2838 
2839 
2847 static void
2849  struct GNUNET_SERVICE_Client *c,
2850  void *internal_cls)
2851 {
2852  GNUNET_assert (c == internal_cls);
2853 }
2854 
2855 
2863 static void
2864 run (void *cls,
2865  const struct GNUNET_CONFIGURATION_Handle *cfg_,
2867 {
2868  char *ifname;
2869  char *ipv6addr;
2870  char *ipv6prefix_s;
2871  char *ipv4addr;
2872  char *ipv4mask;
2873  struct in_addr v4;
2874  struct in6_addr v6;
2875  char *binary;
2876 
2877  binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
2878 
2879  if (GNUNET_YES !=
2881  binary,
2882  GNUNET_YES,
2883  "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
2884  {
2886  "`%s' is not SUID, refusing to run.\n",
2887  "gnunet-helper-vpn");
2888  GNUNET_free (binary);
2889  global_ret = 1;
2890  /* we won't "really" exit here, as the 'service' is still running;
2891  however, as no handlers are registered, the service won't do
2892  anything either */
2893  return;
2894  }
2895  GNUNET_free (binary);
2896  cfg = cfg_;
2897  stats = GNUNET_STATISTICS_create ("vpn", cfg);
2898  if (GNUNET_OK !=
2900  "VPN",
2901  "MAX_MAPPING",
2904  if (GNUNET_OK !=
2906  "VPN",
2907  "MAX_TUNNELS",
2909  max_channel_mappings = 200;
2910 
2911  destination_map =
2913  GNUNET_NO);
2914  destination_heap =
2916  channel_map =
2919 
2920 
2921  vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
2922  if (GNUNET_SYSERR ==
2923  GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname))
2924  {
2927  return;
2928  }
2929  vpn_argv[1] = ifname;
2930  ipv6addr = NULL;
2931  if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
2932  {
2934  "VPN",
2935  "IPV6ADDR",
2936  &ipv6addr) ||
2937  (1 != inet_pton (AF_INET6, ipv6addr, &v6))))
2938  {
2940  "VPN",
2941  "IPV6ADDR",
2942  _ ("Must specify valid IPv6 address"));
2944  GNUNET_free_non_null (ipv6addr);
2945  return;
2946  }
2947  vpn_argv[2] = ipv6addr;
2948  ipv6prefix_s = NULL;
2950  "VPN",
2951  "IPV6PREFIX",
2952  &ipv6prefix_s))
2953  {
2954  GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6PREFIX");
2956  GNUNET_free_non_null (ipv6prefix_s);
2957  return;
2958  }
2959  vpn_argv[3] = ipv6prefix_s;
2961  "VPN",
2962  "IPV6PREFIX",
2963  &ipv6prefix)) ||
2964  (ipv6prefix >= 127))
2965  {
2967  "VPN",
2968  "IPV4MASK",
2969  _ ("Must specify valid IPv6 mask"));
2971  return;
2972  }
2973  }
2974  else
2975  {
2977  _ (
2978  "IPv6 support disabled as this system does not support IPv6\n"));
2979  vpn_argv[2] = GNUNET_strdup ("-");
2980  vpn_argv[3] = GNUNET_strdup ("-");
2981  }
2982  if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
2983  {
2984  ipv4addr = NULL;
2986  "vpn",
2987  "IPV4ADDR",
2988  &ipv4addr) ||
2989  (1 != inet_pton (AF_INET, ipv4addr, &v4))))
2990  {
2992  "VPN",
2993  "IPV4ADDR",
2994  _ ("Must specify valid IPv4 address"));
2996  GNUNET_free_non_null (ipv4addr);
2997  return;
2998  }
2999  vpn_argv[4] = ipv4addr;
3000  ipv4mask = NULL;
3002  "vpn",
3003  "IPV4MASK",
3004  &ipv4mask) ||
3005  (1 != inet_pton (AF_INET, ipv4mask, &v4))))
3006  {
3008  "VPN",
3009  "IPV4MASK",
3010  _ ("Must specify valid IPv4 mask"));
3012  GNUNET_free_non_null (ipv4mask);
3013  return;
3014  }
3015  vpn_argv[5] = ipv4mask;
3016  }
3017  else
3018  {
3020  _ (
3021  "IPv4 support disabled as this system does not support IPv4\n"));
3022  vpn_argv[4] = GNUNET_strdup ("-");
3023  vpn_argv[5] = GNUNET_strdup ("-");
3024  }
3025  vpn_argv[6] = NULL;
3026 
3027  cadet_handle = GNUNET_CADET_connect (cfg_);
3028  // FIXME never opens ports???
3029  helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3030  "gnunet-helper-vpn",
3031  vpn_argv,
3032  &message_token,
3033  NULL,
3034  NULL);
3036 }
3037 
3038 
3043  "vpn",
3045  &run,
3048  NULL,
3049  GNUNET_MQ_hd_var_size (client_redirect_to_ip,
3052  NULL),
3053  GNUNET_MQ_hd_fixed_size (client_redirect_to_service,
3056  NULL),
3058 
3059 
3060 /* end of gnunet-service-vpn.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
struct GNUNET_HashCode service_descriptor
Service descriptor identifying the service.
Definition: vpn.h:116
int GNUNET_HELPER_kill(struct GNUNET_HELPER_Handle *h, int soft_kill)
Sends termination signal to the helper process.
Definition: helper.c:180
Response from the VPN service to a VPN client informing about the IP that was assigned for the reques...
Definition: vpn.h:131
struct GNUNET_CONTAINER_HeapNode * heap_node
Entry for this entry in the destination_heap.
unsigned int header_length
void GNUNET_CADET_disconnect(struct GNUNET_CADET_Handle *handle)
Disconnect from the cadet service.
Definition: cadet_api.c:843
void GNUNET_CONTAINER_heap_update_cost(struct GNUNET_CONTAINER_HeapNode *node, GNUNET_CONTAINER_HeapCostType new_cost)
Updates the cost of any node in the tree.
struct in6_addr source_address
Origin of the packet.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static int udp
Option -u: UDP requested.
Definition: gnunet-vpn.c:76
static void expire_channel(struct ChannelState *except)
We have too many active channels.
const void * msg
Message to transmit, allocated at the end of this struct.
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static void handle_client_redirect_to_service(void *cls, const struct RedirectToServiceRequestMessage *msg)
A client asks us to setup a redirection to a particular peer offering a service.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:670
#define GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE
Type of messages containing an ICMP packet for a service.
int GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
uint16_t proto
Here we get an ETH_P_-number.
static int check_tcp_back(void *cls, const struct GNUNET_EXIT_TcpDataMessage *data)
We got a TCP packet back from the CADET channel.
union ChannelState::@114 destination_ip
Destination IP address used by the source on our end (this is the IP that we pick freely within the V...
static void make_up_icmpv4_payload(struct ChannelState *ts, struct GNUNET_TUN_IPv4Header *ipp, struct GNUNET_TUN_UdpHeader *udp)
Synthesize a plausible ICMP payload for an ICMP error response on the given channel.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
Information we track for each IP address to determine which channel to send the traffic over to the d...
#define GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET
Type of messages containing an ICMP packet for the Internet.
struct in6_addr destination_address
Destination of the packet.
struct GNUNET_CONTAINER_HeapNode * GNUNET_CONTAINER_heap_insert(struct GNUNET_CONTAINER_Heap *heap, void *element, GNUNET_CONTAINER_HeapCostType cost)
Inserts a new element into the heap.
struct ChannelMessageQueueEntry * tmq_head
Head of list of messages scheduled for transmission.
Opaque handle to the service.
Definition: cadet_api.c:38
Handle to a service.
Definition: service.c:116
#define GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED
struct GNUNET_PeerIdentity target
Target peer offering the service.
Definition: vpn.h:111
struct in_addr destination_address
Destination of the packet.
uint8_t protocol
IPPROTO_TCP or IPPROTO_UDP once bound.
#define GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE
Client asks VPN service to setup an IP to redirect traffic to some peer offering a service...
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2734
struct ChannelMessageQueueEntry * next
This is a doubly-linked list.
struct DestinationChannel * next
Kept in a DLL.
The handle to a helper process.
Definition: helper.c:80
struct GNUNET_HELPER_Handle * GNUNET_HELPER_start(int with_control_pipe, const char *binary_name, char *const binary_argv[], GNUNET_MessageTokenizerCallback cb, GNUNET_HELPER_ExceptionCallback exp_cb, void *cb_cls)
Starts a helper and begins reading from it.
Definition: helper.c:491
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1293
struct ChannelMessageQueueEntry * prev
This is a doubly-linked list.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
static int ipv4
Option -4: IPv4 requested.
Definition: gnunet-vpn.c:61
static const char * print_channel_destination(const struct DestinationEntry *de)
Output destination of a channel for diagnostics.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
int32_t af
Address family, AF_INET or AF_INET6, in network byte order.
Definition: exit.h:249
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
void GNUNET_TUN_ipv4toregexsearch(const struct in_addr *ip, uint16_t port, char *rxstr)
Create a regex in rxstr from the given ip and port.
Definition: regex.c:45
#define GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE
Type of messages containing an UDP packet for a service.
union ChannelState::@113 source_ip
IP address of the source on our end, initially uninitialized.
void GNUNET_MQ_env_set_options(struct GNUNET_MQ_Envelope *env, enum GNUNET_MQ_PriorityPreferences pp)
Set application-specific options for this envelope.
Definition: mq.c:1005
#define GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START
Type of messages containing an TCP packet for a service.
static void make_up_icmpv6_payload(struct ChannelState *ts, struct GNUNET_TUN_IPv6Header *ipp, struct GNUNET_TUN_UdpHeader *udp)
Synthesize a plausible ICMP payload for an ICMP error response on the given channel.
uint16_t source_port
Source port used by the sender on our end; 0 for uninitialized.
static void send_to_channel(struct ChannelState *ts, struct GNUNET_MQ_Envelope *env)
Add the given message to the given channel and trigger the transmission process.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we use.
static void expire_destination(struct DestinationEntry *except)
We have too many active destinations.
UDP packet header.
#define GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET
Type of messages containing an UDP packet for the Internet.
#define ETH_P_IPV6
Number for IPv6.
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
static int cleanup_destination(void *cls, const struct GNUNET_HashCode *key, void *value)
Free memory occupied by an entry in the destination map.
static void handle_regex_result(void *cls, const struct GNUNET_PeerIdentity *id, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length)
Regex has found a potential exit peer for us; consider using it.
uint64_t request_id
Unique ID to match the response to a request.
Definition: vpn.h:148
static void handle_udp_back(void *cls, const struct GNUNET_EXIT_UdpReplyMessage *reply)
We got a UDP packet back from the CADET channel.
struct GNUNET_TUN_IcmpHeader icmp_header
ICMP header to use.
Definition: exit.h:287
struct DestinationEntry destination
Destination to which this channel leads.
#define GNUNET_NO
Definition: gnunet_common.h:81
int32_t result_af
Address family desired for the result (AF_INET or AF_INET6 or AF_UNSPEC, in nbo)
Definition: vpn.h:106
Opaque handle to a channel.
Definition: cadet_api.c:80
static int cleanup_channel(void *cls, const struct GNUNET_HashCode *key, void *value)
Free memory occupied by an entry in the channel map.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
Standard IPv4 header.
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
int GNUNET_OS_check_helper_binary(const char *binary, int check_suid, const char *params)
Check whether an executable exists and possibly if the suid bit is set on the file.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct GNUNET_HashCode key
Key under which this entry is in the &#39;destination_map&#39; (only valid if &#39;heap_node != NULL&#39;)...
uint16_t flags
Some flags (unused).
void GNUNET_TUN_calculate_udp4_checksum(const struct GNUNET_TUN_IPv4Header *ip, struct GNUNET_TUN_UdpHeader *udp, const void *payload, uint16_t payload_length)
Calculate IPv4 UDP checksum.
Definition: tun.c:183
int32_t af
Address family, AF_INET or AF_INET6, in network byte order.
Definition: exit.h:73
void GNUNET_log_config_invalid(enum GNUNET_ErrorType kind, const char *section, const char *option, const char *required)
Log error message about invalid configuration option value.
struct GNUNET_TUN_TcpHeader tcp_header
Skeleton of the TCP header to send.
Definition: exit.h:110
struct GNUNET_CONTAINER_HeapNode * heap_node
Heap node for this state in the connections_heap.
int is_service
GNUNET_NO if this is a channel to an Internet-exit, GNUNET_YES if this channel is to a service...
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
int GNUNET_CONTAINER_multihashmap_contains(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Check if the map contains any value under the given key (including values that are NULL)...
uint16_t destination_port
Destination port (in NBO).
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
uint16_t len
Number of bytes of payload.
void GNUNET_TUN_calculate_tcp6_checksum(const struct GNUNET_TUN_IPv6Header *ip, struct GNUNET_TUN_TcpHeader *tcp, const void *payload, uint16_t payload_length)
Calculate IPv6 TCP checksum.
Definition: tun.c:147
#define GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:524
Handle for the service.
static unsigned long long max_destination_mappings
If there are more than this number of address-mappings, old ones will be removed. ...
struct GNUNET_TUN_TcpHeader tcp_header
Skeleton of the TCP header to send.
Definition: exit.h:53
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
static int allocate_v6_address(struct in6_addr *v6)
Allocate an IPv6 address from the range of the channel for a new redirection.
void GNUNET_TUN_initialize_ipv4_header(struct GNUNET_TUN_IPv4Header *ip, uint8_t protocol, uint16_t payload_length, const struct in_addr *src, const struct in_addr *dst)
Initialize an IPv4 header.
Definition: tun.c:46
uint64_t abs_value_us
The actual value.
Message send by the VPN client to the VPN service requesting the setup of a redirection from some IP ...
Definition: vpn.h:38
Internal representation of the hash map.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY.
Definition: exit.h:183
void GNUNET_TUN_calculate_udp6_checksum(const struct GNUNET_TUN_IPv6Header *ip, struct GNUNET_TUN_UdpHeader *udp, const void *payload, uint16_t payload_length)
Calculate IPv6 UDP checksum.
Definition: tun.c:222
GNUNET_SERVICE_MAIN("vpn", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_var_size(client_redirect_to_ip, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, struct RedirectToIpRequestMessage, NULL), GNUNET_MQ_hd_fixed_size(client_redirect_to_service, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE, struct RedirectToServiceRequestMessage, NULL), GNUNET_MQ_handler_end())
Define "main" method using service macro.
static void handle_icmp_back(void *cls, const struct GNUNET_EXIT_IcmpToVPNMessage *i2v)
We got an ICMP packet back from the CADET channel.
struct GNUNET_REGEX_Search * GNUNET_REGEX_search(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *string, GNUNET_REGEX_Found callback, void *callback_cls)
Search for a peer offering a regex matching certain string in the DHT.
struct GNUNET_CADET_Handle * GNUNET_CADET_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the MQ-based cadet service.
Definition: cadet_api.c:977
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg_, struct GNUNET_SERVICE_Handle *service)
Main function that will be run by the scheduler.
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
IPC messages between VPN library and VPN service.
#define GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT
Type of messages containing an TCP packet of an established connection.
Handle to a client that is connected to a service.
Definition: service.c:249
static int global_ret
Return value from main().
Best-effort traffic (i.e.
int32_t af
Address family, AF_INET or AF_INET6, in network byte order.
Definition: exit.h:155
Message send via cadet to an exit daemon to send ICMP data to a local service.
Definition: exit.h:205
#define GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
#define GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
#define GNUNET_TUN_ICMPTYPE6_ECHO_REPLY
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP
VPN service responds to client with an IP to use for the requested redirection.
#define GNUNET_memcpy(dst, src, n)
void * cls
Closure for mv and cb.
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
static char * value
Value of the record to add/remove.
#define GNUNET_APPLICATION_PORT_IPV6_GATEWAY
Internet IPv6 gateway (any TCP/UDP/ICMP).
struct GNUNET_TUN_TcpHeader tcp_header
Skeleton of the TCP header to send.
Definition: exit.h:79
#define GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY
Type of messages containing an UDP packet from a remote host.
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *c, void *internal_cls)
Callback called when a client disconnected from the service.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
void GNUNET_TUN_calculate_tcp4_checksum(const struct GNUNET_TUN_IPv4Header *ip, struct GNUNET_TUN_TcpHeader *tcp, const void *payload, uint16_t payload_length)
Calculate IPv4 TCP checksum.
Definition: tun.c:109
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
static void free_channel_state(struct ChannelState *ts)
Free resources associated with a channel state.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
static struct GNUNET_CONTAINER_Heap * channel_heap
Min-Heap sorted by activity time to expire old mappings; values are of type &#39;struct ChannelState&#39;...
unsigned int GNUNET_MQ_get_length(struct GNUNET_MQ_Handle *mq)
Obtain the current length of the message queue.
Definition: mq.c:335
List of channels we keep for each destination port for a given destination entry. ...
#define GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP
Client asks VPN service to setup an IP to redirect traffic via an exit node to some global IP address...
#define GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG
static int message_token(void *cls, const struct GNUNET_MessageHeader *message)
Receive packets from the helper-process (someone send to the local virtual channel interface)...
uint16_t destination_port
Destination port to use for the UDP request.
Definition: exit.h:165
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
static void cleanup(void *cls)
Function scheduled as very last function, cleans up after us.
#define MAX_MESSAGE_QUEUE_SIZE
Maximum number of messages we allow in the queue for cadet.
static int allocate_response_ip(int *result_af, void **addr, struct in_addr *v4, struct in6_addr *v6)
Allocate an IP address for the response.
void * GNUNET_CONTAINER_heap_peek(const struct GNUNET_CONTAINER_Heap *heap)
Get element stored at the root of heap.
int32_t result_af
Address family desired for the result (AF_INET or AF_INET6 or AF_UNSPEC, in nbo)
Definition: vpn.h:58
int is_established
Is this channel new (GNUNET_NO), or did we exchange messages with the other side already (GNUNET_YES)...
uint32_t reserved
Always 0.
Definition: exit.h:47
Message send via cadet to an exit daemon to forward ICMP data to the Internet.
Definition: exit.h:236
#define GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START
Type of messages containing an TCP packet for the Internet.
#define GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN
Type of messages containing an TCP packet of an established connection.
static unsigned long long max_channel_mappings
If there are more than this number of open channels, old ones will be removed.
static char buf[2048]
int GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
int af
Addess family used for this channel on the local TUN interface.
Handle to a node in a heap.
static struct GNUNET_CONTAINER_MultiHashMap * destination_map
Map from IP address to destination information (possibly with a CADET channel handle for fast setup)...
int32_t af
Address family, AF_INET or AF_INET6, in network byte order.
Definition: exit.h:282
void GNUNET_REGEX_search_cancel(struct GNUNET_REGEX_Search *s)
Stop search and free all data used by a GNUNET_REGEX_search call.
A messages we have in queue for a particular channel.
size_t len
Number of bytes in msg.
static struct GNUNET_CADET_Handle * cadet_handle
Handle to the cadet service.
Heap with the minimum cost at the root.
static void free_destination_entry(struct DestinationEntry *de)
Free resources occupied by a destination entry.
void GNUNET_CONTAINER_heap_destroy(struct GNUNET_CONTAINER_Heap *heap)
Destroys the heap.
A 512-bit hashcode.
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2618
Header from Linux TUN interface.
uint8_t next_header
For example, IPPROTO_UDP or IPPROTO_TCP.
Message send from exit daemon back to the UDP entry point (used for both Internet and Service exit re...
Definition: exit.h:178
union DestinationEntry::@109 details
Details about the connection (depending on is_service).
static void get_destination_key_from_ip(int af, const void *address, struct GNUNET_HashCode *key)
Compute the key under which we would store an entry in the destination_map for the given IP address...
Message handler for a specific message type.
uint16_t destination_port
Destination port (in NBO).
static int res
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
struct GNUNET_CADET_Channel * channel
Cadet channel that is used for this connection.
static void route_packet(struct DestinationEntry *destination, int af, uint8_t protocol, const void *source_ip, const void *destination_ip, const void *payload, size_t payload_length)
Route a packet via cadet to the given destination.
static void get_channel_key_from_ips(int af, uint8_t protocol, const void *source_ip, uint16_t source_port, const void *destination_ip, uint16_t destination_port, struct GNUNET_HashCode *key)
Compute the key under which we would store an entry in the channel_map for the given socket address p...
void GNUNET_TUN_ipv6toregexsearch(const struct in6_addr *ipv6, uint16_t port, char *rxstr)
Create a regex in rxstr from the given ipv6 and port.
Definition: regex.c:66
int GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
void GNUNET_MQ_discard(struct GNUNET_MQ_Envelope *mqm)
Discard the message queue message, free all allocated resources.
Definition: mq.c:321
uint16_t source_port
Source port to use for the UDP reply (0 to use the same port as for the original request).
Definition: exit.h:189
static char * vpn_argv[7]
Arguments to the vpn helper.
Node in the heap.
#define GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX
Internet exit regex prefix.
struct in_addr v4
Address if af is AF_INET.
struct in6_addr v6
Address if af is AF_INET6.
void GNUNET_TUN_compute_service_cadet_port(const struct GNUNET_HashCode *desc, uint16_t ip_port, struct GNUNET_HashCode *cadet_port)
Compute the CADET port given a service descriptor (returned from GNUNET_TUN_service_name_to_hash) and...
Definition: regex.c:823
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP.
Definition: vpn.h:43
There must only be one value per key; storing a value should fail if a value under the same key alrea...
format for cadet messages exchanged between VPN service and exit daemon
struct in_addr v4
Address if af is AF_INET.
struct GNUNET_HashCode key
The key used in the DHT.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static struct ChannelState * create_channel_to_destination(struct DestinationChannel *dt, int client_af)
Initialize the given destination entry&#39;s cadet channel.
static unsigned int size
Size of the "table".
Definition: peer.c:67
struct DestinationEntry::@109::@110 service_destination
int32_t result_af
Address family of the allocated address that follows; will match "result_af" from the request...
Definition: vpn.h:143
#define GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE
static int check_client_redirect_to_ip(void *cls, const struct RedirectToIpRequestMessage *msg)
A client asks us to setup a redirection via some exit node to a particular IP.
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
void GNUNET_TUN_calculate_icmp_checksum(struct GNUNET_TUN_IcmpHeader *icmp, const void *payload, uint16_t payload_length)
Calculate ICMP checksum.
Definition: tun.c:260
#define GNUNET_TUN_IPV4_REGEXLEN
Maximum regex string length for use with GNUNET_TUN_ipv4toregexsearch.
static void handle_client_redirect_to_ip(void *cls, const struct RedirectToIpRequestMessage *msg)
A client asks us to setup a redirection via some exit node to a particular IP.
static struct GNUNET_CONTAINER_MultiHashMap * channel_map
Map from source and destination address (IP+port) to connection information (mostly with the respecti...
static void send_client_reply(struct GNUNET_SERVICE_Client *client, uint64_t request_id, int result_af, const void *addr)
Notify the client about the result of its request.
Message send via cadet to the vpn service to send ICMP data to the VPN&#39;s TUN interface.
Definition: exit.h:271
TCP packet header.
struct DestinationEntry * destination
Destination entry list this struct DestinationChannel belongs with.
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
static unsigned long long payload
How much data are we currently storing in the database?
uint16_t destination_port
Destination port this channel state is used for.
uint16_t crc
Checksum.
struct GNUNET_CONTAINER_Heap * GNUNET_CONTAINER_heap_create(enum GNUNET_CONTAINER_HeapOrder order)
Create a new heap.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
struct GNUNET_TIME_AbsoluteNBO expiration_time
How long should the redirection be maintained at most?
Definition: vpn.h:96
static int tcp
Option -t: TCP requested.
Definition: gnunet-vpn.c:71
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message...
Standard IPv6 header.
static void handle_tcp_back(void *cls, const struct GNUNET_EXIT_TcpDataMessage *data)
We got a TCP packet back from the CADET channel.
#define GNUNET_TUN_ICMPTYPE_ECHO_REQUEST
#define GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM
Message send via cadet to an exit daemon to send UDP data to a local service.
Definition: exit.h:120
uint64_t request_id
Unique ID to match a future response to this request.
Definition: vpn.h:122
uint8_t protocol
L4-protocol, for example, IPPROTO_UDP or IPPROTO_TCP.
uint16_t source_port
Source port (in NBO).
Allow multiple values with the same key.
Handle to a message queue.
Definition: mq.c:85
The identity of the host (wraps the signing key of the peer).
#define GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST
void GNUNET_CADET_receive_done(struct GNUNET_CADET_Channel *channel)
Send an ack on the channel to confirm the processing of a message.
Definition: cadet_api.c:955
static struct GNUNET_STATISTICS_Handle * stats
Statistics.
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to &#39;struct&#39;s...
struct GNUNET_CADET_Channel * GNUNET_CADET_channel_create(struct GNUNET_CADET_Handle *h, void *channel_cls, const struct GNUNET_PeerIdentity *destination, const struct GNUNET_HashCode *port, GNUNET_CADET_WindowSizeEventHandler window_changes, GNUNET_CADET_DisconnectEventHandler disconnects, const struct GNUNET_MQ_MessageHandler *handlers)
Create a new channel towards a remote peer.
Definition: cadet_api.c:1070
#define GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN
Type of messages containing an ICMP packet for the VPN.
static uint16_t port
Port number.
Definition: gnunet-bcd.c:79
configuration data
Definition: configuration.c:85
struct DestinationChannel * dt_head
Head of DLL of channels associated with this destination.
uint16_t source_port
Source port (in NBO).
int32_t addr_af
Address family used for the destination address (AF_INET or AF_INET6, in nbo)
Definition: vpn.h:63
static void channel_cleaner(void *cls, const struct GNUNET_CADET_Channel *channel)
Function called whenever a channel is destroyed.
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *c, struct GNUNET_MQ_Handle *mq)
Callback called when a client connects to the service.
struct GNUNET_TIME_AbsoluteNBO expiration_time
How long should the redirection be maintained at most?
Definition: vpn.h:53
int af
Address family used (AF_INET or AF_INET6).
struct ChannelMessageQueueEntry * tmq_tail
Tail of list of messages scheduled for transmission.
struct GNUNET_HELPER_SendHandle * GNUNET_HELPER_send(struct GNUNET_HELPER_Handle *h, const struct GNUNET_MessageHeader *msg, int can_drop, GNUNET_HELPER_Continuation cont, void *cont_cls)
Send an message to the helper.
Definition: helper.c:660
uint16_t destination_port
Destination port used by the sender on our end; 0 for uninitialized.
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
static int allocate_v4_address(struct in_addr *v4)
Allocate an IPv4 address from the range of the channel for a new redirection.
static int inet_pton(int af, const char *cp, struct in_addr *buf)
Convert IPv4 address from text to binary form.
#define GNUNET_log(kind,...)
Flag to indicate that out-of-order delivery is OK.
int GNUNET_HELPER_wait(struct GNUNET_HELPER_Handle *h)
Reap the helper process.
Definition: helper.c:231
static unsigned long long ipv6prefix
Length of the prefix of the VPN&#39;s IPv6 network.
Message send via cadet to an exit daemon to initiate forwarding of TCP data to the Internet...
Definition: exit.h:63
char * GNUNET_OS_get_libexec_binary_path(const char *progname)
Given the name of a gnunet-helper, gnunet-service or gnunet-daemon binary, try to prefix it with the ...
int32_t af
Address family, AF_INET or AF_INET6, in network byte order.
Definition: exit.h:218
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
struct GNUNET_REGEX_Search * search
Active query with REGEX to locate exit.
struct DestinationEntry::@109::@111 exit_destination
struct in_addr source_address
Origin of the packet.
uint16_t destination_port
Destination port to use for the UDP reply (0 to use the same port as for the original request)...
Definition: exit.h:195
struct GNUNET_MessageHeader header
Type is #GNUNET_MESSAGE_TYPE_VPN_TCP_DATA.
Definition: exit.h:99
Header for all communications.
This struct is saved into connections_map to allow finding the right channel given an IP packet from ...
#define GNUNET_YES
Definition: gnunet_common.h:80
struct DestinationChannel * prev
Kept in a DLL.
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:353
static int check_udp_back(void *cls, const struct GNUNET_EXIT_UdpReplyMessage *reply)
We got a UDP packet back from the CADET channel.
static struct GNUNET_CADET_Channel * create_channel(struct ChannelState *ts, const struct GNUNET_PeerIdentity *target, const struct GNUNET_HashCode *port)
Create a channel for ts to target at port.
static struct GNUNET_CONTAINER_Heap * destination_heap
Min-Heap sorted by activity time to expire old mappings.
commonly used definitions; globals in this file are exempt from the rule that the module name ("commo...
struct GNUNET_MQ_Envelope * GNUNET_MQ_unsent_head(struct GNUNET_MQ_Handle *mq)
Remove the first envelope that has not yet been sent from the message queue and return it...
Definition: mq.c:394
unsigned int tmq_length
Length of the doubly linked &#39;tmq_head/tmq_tail&#39; list.
struct GNUNET_MessageHeader header
Type is GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN.
Definition: exit.h:276
uint64_t request_id
Unique ID to match a future response to this request.
Definition: vpn.h:69
unsigned int off
Number of 32-bit words in TCP header.
Handle to store data about a regex search.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
uint16_t source_port
Source port to use for the UDP request (0 to use a random port).
Definition: exit.h:160
Message send via cadet to an exit daemon to initiate forwarding of TCP data to a local service...
Definition: exit.h:37
uint32_t data
The data value.
void * GNUNET_CONTAINER_heap_remove_node(struct GNUNET_CONTAINER_HeapNode *node)
Removes a node from the heap.
#define GNUNET_TUN_ICMPTYPE_ECHO_REPLY
static int check_icmp_back(void *cls, const struct GNUNET_EXIT_IcmpToVPNMessage *i2v)
We got an ICMP packet back from the CADET channel.
#define GNUNET_APPLICATION_PORT_IPV4_GATEWAY
Internet IPv4 gateway (any TCP/UDP/ICMP).
static char * address
GNS address for this phone.
struct DestinationChannel * dt_tail
Tail of DLL of channels associated with this destination.
Message send via cadet between VPN and entry and an exit daemon to transmit TCP data between the VPN ...
Definition: exit.h:94
void GNUNET_CADET_channel_destroy(struct GNUNET_CADET_Channel *channel)
Destroy an existing channel.
Definition: cadet_api.c:905
uint32_t reserved
Always 0.
Definition: exit.h:104
struct GNUNET_TUN_IcmpHeader icmp_header
ICMP header to use.
Definition: exit.h:223
static struct GNUNET_HELPER_Handle * helper_handle
The handle to the VPN helper process "gnunet-helper-vpn".
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2533
void GNUNET_TUN_initialize_ipv6_header(struct GNUNET_TUN_IPv6Header *ip, uint8_t protocol, uint16_t payload_length, const struct in6_addr *src, const struct in6_addr *dst)
Initialize an IPv6 header.
Definition: tun.c:81
uint16_t source_port
Source port to use for the UDP request (0 to use a random port).
Definition: exit.h:130
struct GNUNET_TUN_IcmpHeader icmp_header
ICMP header to use.
Definition: exit.h:255
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define ETH_P_IPV4
Number for IPv4.
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
Message send by the VPN client to the VPN service requesting the setup of a redirection from some IP ...
Definition: vpn.h:81
#define GNUNET_TUN_IPV6_REGEXLEN
Maximum regex string length for use with GNUNET_TUN_ipv6toregexsearch.
int GNUNET_NETWORK_test_pf(int pf)
Test if the given protocol family is supported by this system.
Definition: network.c:84
Message send via cadet to an exit daemon to forward UDP data to the Internet.
Definition: exit.h:145
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_MESSAGE_TYPE_VPN_HELPER
Type of messages between the gnunet-vpn-helper and the daemon.
struct in6_addr v6
Address if af is AF_INET6.
#define gettext_noop(String)
Definition: gettext.h:69
struct GNUNET_MQ_Handle * GNUNET_CADET_get_mq(const struct GNUNET_CADET_Channel *channel)
Obtain the message queue for a connected peer.
Definition: cadet_api.c:1121
static int ipv6
Option -6: IPv6 requested.
Definition: gnunet-vpn.c:66
uint16_t destination_port
Destination port to use for the UDP request.
Definition: exit.h:135