summaryrefslogtreecommitdiff
path: root/src/vpn
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-02-22 17:32:15 +0100
committerChristian Grothoff <christian@grothoff.org>2017-02-22 17:32:15 +0100
commit88a0df3dcc38c6e82f483bff386c87d8e1ec4459 (patch)
treec086b6c30a6fc54e0d72aabe7857f3b659915caa /src/vpn
parent85088f7eedd1146890a5ce9af05fff934a5b1b8d (diff)
converting 'vpn' to new CADET API, not tested/testable, as exit is not converted yet
Diffstat (limited to 'src/vpn')
-rw-r--r--src/vpn/Makefile.am4
-rw-r--r--src/vpn/gnunet-service-vpn.c1753
2 files changed, 844 insertions, 913 deletions
diff --git a/src/vpn/Makefile.am b/src/vpn/Makefile.am
index 5517a45e3..417d2eb89 100644
--- a/src/vpn/Makefile.am
+++ b/src/vpn/Makefile.am
@@ -59,7 +59,7 @@ gnunet_service_vpn_LDADD = \
$(top_builddir)/src/statistics/libgnunetstatistics.la \
$(top_builddir)/src/tun/libgnunettun.la \
$(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/cadet/libgnunetcadet.la \
+ $(top_builddir)/src/cadet/libgnunetcadetnew.la \
$(top_builddir)/src/regex/libgnunetregex.la \
$(GN_LIBINTL)
gnunet_service_vpn_CFLAGS = \
@@ -79,5 +79,3 @@ libgnunetvpn_la_LIBADD = \
$(top_builddir)/src/util/libgnunetutil.la $(XLIB)
libgnunetvpn_la_LDFLAGS = \
$(GN_LIB_LDFLAGS)
-
-
diff --git a/src/vpn/gnunet-service-vpn.c b/src/vpn/gnunet-service-vpn.c
index c66023c85..aa0ea51a3 100644
--- a/src/vpn/gnunet-service-vpn.c
+++ b/src/vpn/gnunet-service-vpn.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2010, 2011, 2012, 2016 Christian Grothoff
+ Copyright (C) 2010, 2011, 2012, 2016, 2017 Christian Grothoff
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
@@ -221,11 +221,6 @@ struct ChannelState
struct GNUNET_REGEX_Search *search;
/**
- * Active transmission handle, NULL for none.
- */
- struct GNUNET_CADET_TransmitHandle *th;
-
- /**
* Entry for this entry in the channel_heap, NULL as long as this
* channel state is not fully bound.
*/
@@ -535,11 +530,6 @@ free_channel_state (struct ChannelState *ts)
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Cleaning up channel state\n");
- if (NULL != ts->th)
- {
- GNUNET_CADET_notify_transmit_ready_cancel (ts->th);
- ts->th = NULL;
- }
if (NULL != (channel = ts->channel))
{
ts->channel = NULL;
@@ -585,97 +575,32 @@ free_channel_state (struct ChannelState *ts)
/**
- * Send a message from the message queue via cadet.
- *
- * @param cls the `struct ChannelState` with the message queue
- * @param size number of bytes available in @a buf
- * @param buf where to copy the message
- * @return number of bytes copied to @a buf
- */
-static size_t
-send_to_peer_notify_callback (void *cls, size_t size, void *buf)
-{
- struct ChannelState *ts = cls;
- struct ChannelMessageQueueEntry *tnq;
- size_t ret;
-
- ts->th = NULL;
- if (NULL == buf)
- return 0;
- tnq = ts->tmq_head;
- GNUNET_assert (NULL != tnq);
- GNUNET_assert (size >= tnq->len);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Sending %u bytes via cadet channel\n",
- (unsigned int) tnq->len);
- GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
- ts->tmq_tail,
- tnq);
- ts->tmq_length--;
- GNUNET_memcpy (buf, tnq->msg, tnq->len);
- ret = tnq->len;
- GNUNET_free (tnq);
- if (NULL != (tnq = ts->tmq_head))
- {
- if (NULL == ts->th)
- ts->th = GNUNET_CADET_notify_transmit_ready (ts->channel,
- GNUNET_NO /* cork */,
- GNUNET_TIME_UNIT_FOREVER_REL,
- tnq->len,
- &send_to_peer_notify_callback,
- ts);
- }
- GNUNET_STATISTICS_update (stats,
- gettext_noop ("# Bytes given to cadet for transmission"),
- ret, GNUNET_NO);
- return ret;
-}
-
-
-/**
* Add the given message to the given channel and trigger the
* transmission process.
*
- * @param tnq message to queue
* @param ts channel to queue the message for
+ * @param env message to queue
*/
static void
-send_to_channel (struct ChannelMessageQueueEntry *tnq,
- struct ChannelState *ts)
+send_to_channel (struct ChannelState *ts,
+ struct GNUNET_MQ_Envelope *env)
{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Queueing %u bytes for transmission via cadet channel\n",
- (unsigned int) tnq->len);
+ struct GNUNET_MQ_Handle *mq;
+
GNUNET_assert (NULL != ts->channel);
- GNUNET_CONTAINER_DLL_insert_tail (ts->tmq_head,
- ts->tmq_tail,
- tnq);
- ts->tmq_length++;
- if (ts->tmq_length > MAX_MESSAGE_QUEUE_SIZE)
+ mq = GNUNET_CADET_get_mq (ts->channel);
+ GNUNET_MQ_send (mq,
+ env);
+ if (GNUNET_MQ_get_length (mq) > MAX_MESSAGE_QUEUE_SIZE)
{
- struct ChannelMessageQueueEntry *dq;
-
- dq = ts->tmq_head;
- GNUNET_assert (dq != tnq);
- GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
- ts->tmq_tail,
- dq);
- ts->tmq_length--;
- GNUNET_CADET_notify_transmit_ready_cancel (ts->th);
- ts->th = NULL;
+ env = GNUNET_MQ_unsent_head (mq);
+ GNUNET_assert (NULL != env);
GNUNET_STATISTICS_update (stats,
- gettext_noop ("# Bytes dropped in cadet queue (overflow)"),
- dq->len,
+ gettext_noop ("# Messages dropped in cadet queue (overflow)"),
+ 1,
GNUNET_NO);
- GNUNET_free (dq);
+ GNUNET_MQ_discard (env);
}
- if (NULL == ts->th)
- ts->th = GNUNET_CADET_notify_transmit_ready (ts->channel,
- GNUNET_NO /* cork */,
- GNUNET_TIME_UNIT_FOREVER_REL,
- tnq->len,
- &send_to_peer_notify_callback,
- ts);
}
@@ -710,6 +635,767 @@ print_channel_destination (const struct DestinationEntry *de)
/**
+ * Function called whenever a channel is destroyed. Should clean up
+ * any associated state.
+ *
+ * @param cls our `struct ChannelState`
+ * @param channel connection to the other end (henceforth invalid)
+ */
+static void
+channel_cleaner (void *cls,
+ const struct GNUNET_CADET_Channel *channel)
+{
+ struct ChannelState *ts = cls;
+
+ ts->channel = NULL; /* we must not call GNUNET_CADET_channel_destroy() anymore */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "CADET notified us about death of channel to `%s'\n",
+ print_channel_destination (&ts->destination));
+ free_channel_state (ts);
+}
+
+
+/**
+ * Synthesize a plausible ICMP payload for an ICMP error
+ * response on the given channel.
+ *
+ * @param ts channel information
+ * @param ipp IPv4 header to fill in (ICMP payload)
+ * @param udp "UDP" header to fill in (ICMP payload); might actually
+ * also be the first 8 bytes of the TCP header
+ */
+static void
+make_up_icmpv4_payload (struct ChannelState *ts,
+ struct GNUNET_TUN_IPv4Header *ipp,
+ struct GNUNET_TUN_UdpHeader *udp)
+{
+ GNUNET_TUN_initialize_ipv4_header (ipp,
+ ts->protocol,
+ sizeof (struct GNUNET_TUN_TcpHeader),
+ &ts->source_ip.v4,
+ &ts->destination_ip.v4);
+ udp->source_port = htons (ts->source_port);
+ udp->destination_port = htons (ts->destination_port);
+ udp->len = htons (0);
+ udp->crc = htons (0);
+}
+
+
+/**
+ * Synthesize a plausible ICMP payload for an ICMP error
+ * response on the given channel.
+ *
+ * @param ts channel information
+ * @param ipp IPv6 header to fill in (ICMP payload)
+ * @param udp "UDP" header to fill in (ICMP payload); might actually
+ * also be the first 8 bytes of the TCP header
+ */
+static void
+make_up_icmpv6_payload (struct ChannelState *ts,
+ struct GNUNET_TUN_IPv6Header *ipp,
+ struct GNUNET_TUN_UdpHeader *udp)
+{
+ GNUNET_TUN_initialize_ipv6_header (ipp,
+ ts->protocol,
+ sizeof (struct GNUNET_TUN_TcpHeader),
+ &ts->source_ip.v6,
+ &ts->destination_ip.v6);
+ udp->source_port = htons (ts->source_port);
+ udp->destination_port = htons (ts->destination_port);
+ udp->len = htons (0);
+ udp->crc = htons (0);
+}
+
+
+/**
+ * We got an ICMP packet back from the CADET channel. Check it is OK.
+ *
+ * @param cls our `struct ChannelState *`
+ * @param message the actual message
+ * @return #GNUNET_OK to keep the connection open,
+ * #GNUNET_SYSERR to close it (signal serious error)
+ */
+static int
+check_icmp_back (void *cls,
+ const struct GNUNET_EXIT_IcmpToVPNMessage *i2v)
+{
+ struct ChannelState *ts = cls;
+
+ if (NULL == ts->heap_node)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ if (AF_UNSPEC == ts->af)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * We got an ICMP packet back from the CADET channel. Pass it on to the
+ * local virtual interface via the helper.
+ *
+ * @param cls our `struct ChannelState *`
+ * @param message the actual message
+ */
+static void
+handle_icmp_back (void *cls,
+ const struct GNUNET_EXIT_IcmpToVPNMessage *i2v)
+{
+ struct ChannelState *ts = cls;
+ size_t mlen;
+
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# ICMP packets received from cadet"),
+ 1,
+ GNUNET_NO);
+ mlen = ntohs (i2v->header.size) - sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
+ {
+ char sbuf[INET6_ADDRSTRLEN];
+ char dbuf[INET6_ADDRSTRLEN];
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received ICMP packet from cadet, sending %u bytes from %s -> %s via TUN\n",
+ (unsigned int) mlen,
+ inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
+ inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
+ }
+ switch (ts->af)
+ {
+ case AF_INET:
+ {
+ size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
+ + sizeof (struct GNUNET_TUN_IcmpHeader)
+ + sizeof (struct GNUNET_MessageHeader) +
+ sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
+ mlen;
+ {
+ /* reserve some extra space in case we have an ICMP type here where
+ we will need to make up the payload ourselves */
+ char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
+ struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
+ struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
+ struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
+ struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
+ msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
+ tun->flags = htons (0);
+ tun->proto = htons (ETH_P_IPV4);
+ GNUNET_TUN_initialize_ipv4_header (ipv4,
+ IPPROTO_ICMP,
+ sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
+ &ts->destination_ip.v4,
+ &ts->source_ip.v4);
+ *icmp = i2v->icmp_header;
+ GNUNET_memcpy (&icmp[1],
+ &i2v[1],
+ mlen);
+ /* For some ICMP types, we need to adjust (make up) the payload here.
+ Also, depending on the AF used on the other side, we have to
+ do ICMP PT (translate ICMP types) */
+ switch (ntohl (i2v->af))
+ {
+ case AF_INET:
+ switch (icmp->type)
+ {
+ case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
+ case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
+ break;
+ case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
+ case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
+ case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
+ {
+ struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
+ struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
+
+ if (mlen != 0)
+ {
+ /* sender did not strip ICMP payload? */
+ GNUNET_break_op (0);
+ return;
+ }
+ size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
+ GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
+ make_up_icmpv4_payload (ts, ipp, udp);
+ }
+ break;
+ default:
+ GNUNET_break_op (0);
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
+ 1, GNUNET_NO);
+ return;
+ }
+ /* end AF_INET */
+ break;
+ case AF_INET6:
+ /* ICMP PT 6-to-4 and possibly making up payloads */
+ switch (icmp->type)
+ {
+ case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
+ icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
+ {
+ struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
+ struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
+
+ if (mlen != 0)
+ {
+ /* sender did not strip ICMP payload? */
+ GNUNET_break_op (0);
+ return;
+ }
+ size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
+ GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
+ make_up_icmpv4_payload (ts, ipp, udp);
+ }
+ break;
+ case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
+ icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
+ {
+ struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
+ struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
+
+ if (mlen != 0)
+ {
+ /* sender did not strip ICMP payload? */
+ GNUNET_break_op (0);
+ return;
+ }
+ size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
+ GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
+ make_up_icmpv4_payload (ts, ipp, udp);
+ }
+ break;
+ case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
+ case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
+ 1, GNUNET_NO);
+ return;
+ case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
+ icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
+ break;
+ case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
+ icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
+ break;
+ default:
+ GNUNET_break_op (0);
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
+ 1, GNUNET_NO);
+ return;
+ }
+ /* end AF_INET6 */
+ break;
+ default:
+ GNUNET_break_op (0);
+ return;
+ }
+ msg->size = htons (size);
+ GNUNET_TUN_calculate_icmp_checksum (icmp,
+ &i2v[1],
+ mlen);
+ (void) GNUNET_HELPER_send (helper_handle,
+ msg,
+ GNUNET_YES,
+ NULL, NULL);
+ }
+ }
+ break;
+ case AF_INET6:
+ {
+ size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
+ + sizeof (struct GNUNET_TUN_IcmpHeader)
+ + sizeof (struct GNUNET_MessageHeader) +
+ sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
+ mlen;
+ {
+ char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
+ struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
+ struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
+ struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
+ struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
+ msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
+ tun->flags = htons (0);
+ tun->proto = htons (ETH_P_IPV6);
+ GNUNET_TUN_initialize_ipv6_header (ipv6,
+ IPPROTO_ICMPV6,
+ sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
+ &ts->destination_ip.v6,
+ &ts->source_ip.v6);
+ *icmp = i2v->icmp_header;
+ GNUNET_memcpy (&icmp[1],
+ &i2v[1],
+ mlen);
+
+ /* For some ICMP types, we need to adjust (make up) the payload here.
+ Also, depending on the AF used on the other side, we have to
+ do ICMP PT (translate ICMP types) */
+ switch (ntohl (i2v->af))
+ {
+ case AF_INET:
+ /* ICMP PT 4-to-6 and possibly making up payloads */
+ switch (icmp->type)
+ {
+ case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
+ icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
+ break;
+ case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
+ icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
+ break;
+ case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
+ icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
+ {
+ struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
+ struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
+
+ if (mlen != 0)
+ {
+ /* sender did not strip ICMP payload? */
+ GNUNET_break_op (0);
+ return;
+ }
+ size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
+ GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
+ make_up_icmpv6_payload (ts, ipp, udp);
+ }
+ break;
+ case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
+ icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
+ {
+ struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
+ struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
+
+ if (mlen != 0)
+ {
+ /* sender did not strip ICMP payload? */
+ GNUNET_break_op (0);
+ return;
+ }
+ size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
+ GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
+ make_up_icmpv6_payload (ts, ipp, udp);
+ }
+ break;
+ case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
+ 1, GNUNET_NO);
+ return;
+ default:
+ GNUNET_break_op (0);
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
+ 1, GNUNET_NO);
+ return;
+ }
+ /* end AF_INET */
+ break;
+ case AF_INET6:
+ switch (icmp->type)
+ {
+ case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
+ case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
+ case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
+ case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
+ {
+ struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
+ struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
+
+ if (mlen != 0)
+ {
+ /* sender did not strip ICMP payload? */
+ GNUNET_break_op (0);
+ return;
+ }
+ size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
+ GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
+ make_up_icmpv6_payload (ts, ipp, udp);
+ }
+ break;
+ case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
+ break;
+ default:
+ GNUNET_break_op (0);
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
+ 1, GNUNET_NO);
+ return;
+ }
+ /* end AF_INET6 */
+ break;
+ default:
+ GNUNET_break_op (0);
+ return;
+ }
+ msg->size = htons (size);
+ GNUNET_TUN_calculate_icmp_checksum (icmp,
+ &i2v[1], mlen);
+ (void) GNUNET_HELPER_send (helper_handle,
+ msg,
+ GNUNET_YES,
+ NULL, NULL);
+ }
+ }
+ break;
+ default:
+ GNUNET_assert (0);
+ }
+ GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
+ GNUNET_TIME_absolute_get ().abs_value_us);
+ GNUNET_CADET_receive_done (ts->channel);
+}
+
+
+/**
+ * We got a UDP packet back from the CADET channel. Check that it is OK.
+ *
+ * @param cls our `struct ChannelState *`
+ * @param reply the actual message
+ * @return #GNUNET_OK to keep the connection open,
+ * #GNUNET_SYSERR to close it (signal serious error)
+ */
+static int
+check_udp_back (void *cls,
+ const struct GNUNET_EXIT_UdpReplyMessage *reply)
+{
+ struct ChannelState *ts = cls;
+
+ if (NULL == ts->heap_node)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ if (AF_UNSPEC == ts->af)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * We got a UDP packet back from the CADET channel. Pass it on to the
+ * local virtual interface via the helper.
+ *
+ * @param cls our `struct ChannelState *`
+ * @param reply the actual message
+ */
+static void
+handle_udp_back (void *cls,
+ const struct GNUNET_EXIT_UdpReplyMessage *reply)
+{
+ struct ChannelState *ts = cls;
+ size_t mlen;
+
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# UDP packets received from cadet"),
+ 1,
+ GNUNET_NO);
+ mlen = ntohs (reply->header.size) - sizeof (struct GNUNET_EXIT_UdpReplyMessage);
+ {
+ char sbuf[INET6_ADDRSTRLEN];
+ char dbuf[INET6_ADDRSTRLEN];
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received UDP reply from cadet, sending %u bytes from [%s]:%u -> [%s]:%u via TUN\n",
+ (unsigned int) mlen,
+ inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
+ ts->destination_port,
+ inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
+ ts->source_port);
+ }
+ switch (ts->af)
+ {
+ case AF_INET:
+ {
+ size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
+ + sizeof (struct GNUNET_TUN_UdpHeader)
+ + sizeof (struct GNUNET_MessageHeader) +
+ sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
+ mlen;
+ {
+ char buf[size] GNUNET_ALIGN;
+ struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
+ struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
+ struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
+ struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
+ msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
+ msg->size = htons (size);
+ tun->flags = htons (0);
+ tun->proto = htons (ETH_P_IPV4);
+ GNUNET_TUN_initialize_ipv4_header (ipv4,
+ IPPROTO_UDP,
+ sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
+ &ts->destination_ip.v4,
+ &ts->source_ip.v4);
+ if (0 == ntohs (reply->source_port))
+ udp->source_port = htons (ts->destination_port);
+ else
+ udp->source_port = reply->source_port;
+ if (0 == ntohs (reply->destination_port))
+ udp->destination_port = htons (ts->source_port);
+ else
+ udp->destination_port = reply->destination_port;
+ udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
+ GNUNET_TUN_calculate_udp4_checksum (ipv4,
+ udp,
+ &reply[1],
+ mlen);
+ GNUNET_memcpy (&udp[1],
+ &reply[1],
+ mlen);
+ (void) GNUNET_HELPER_send (helper_handle,
+ msg,
+ GNUNET_YES,
+ NULL, NULL);
+ }
+ }
+ break;
+ case AF_INET6:
+ {
+ size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
+ + sizeof (struct GNUNET_TUN_UdpHeader)
+ + sizeof (struct GNUNET_MessageHeader) +
+ sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
+ mlen;
+ {
+ char buf[size] GNUNET_ALIGN;
+ struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
+ struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
+ struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
+ struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
+ msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
+ msg->size = htons (size);
+ tun->flags = htons (0);
+ tun->proto = htons (ETH_P_IPV6);
+ GNUNET_TUN_initialize_ipv6_header (ipv6,
+ IPPROTO_UDP,
+ sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
+ &ts->destination_ip.v6,
+ &ts->source_ip.v6);
+ if (0 == ntohs (reply->source_port))
+ udp->source_port = htons (ts->destination_port);
+ else
+ udp->source_port = reply->source_port;
+ if (0 == ntohs (reply->destination_port))
+ udp->destination_port = htons (ts->source_port);
+ else
+ udp->destination_port = reply->destination_port;
+ udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
+ GNUNET_TUN_calculate_udp6_checksum (ipv6,
+ udp,
+ &reply[1], mlen);
+ GNUNET_memcpy (&udp[1],
+ &reply[1],
+ mlen);
+ (void) GNUNET_HELPER_send (helper_handle,
+ msg,
+ GNUNET_YES,
+ NULL, NULL);
+ }
+ }
+ break;
+ default:
+ GNUNET_assert (0);
+ }
+ GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
+ GNUNET_TIME_absolute_get ().abs_value_us);
+ GNUNET_CADET_receive_done (ts->channel);
+}
+
+
+/**
+ * We got a TCP packet back from the CADET channel. Check it is OK.
+ *
+ * @param cls our `struct ChannelState *`
+ * @param data the actual message
+ * @return #GNUNET_OK to keep the connection open,
+ * #GNUNET_SYSERR to close it (signal serious error)
+ */
+static int
+check_tcp_back (void *cls,
+ const struct GNUNET_EXIT_TcpDataMessage *data)
+{
+ struct ChannelState *ts = cls;
+
+ if (NULL == ts->heap_node)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * We got a TCP packet back from the CADET channel. Pass it on to the
+ * local virtual interface via the helper.
+ *
+ * @param cls our `struct ChannelState *`
+ * @param data the actual message
+ */
+static void
+handle_tcp_back (void *cls,
+ const struct GNUNET_EXIT_TcpDataMessage *data)
+{
+ struct ChannelState *ts = cls;
+ size_t mlen;
+
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# TCP packets received from cadet"),
+ 1,
+ GNUNET_NO);
+ mlen = ntohs (data->header.size) - sizeof (struct GNUNET_EXIT_TcpDataMessage);
+ {
+ char sbuf[INET6_ADDRSTRLEN];
+ char dbuf[INET6_ADDRSTRLEN];
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received TCP reply from cadet, sending %u bytes from [%s]:%u -> [%s]:%u via TUN\n",
+ (unsigned int) mlen,
+ inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
+ ts->destination_port,
+ inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
+ ts->source_port);
+ }
+ switch (ts->af)
+ {
+ case AF_INET:
+ {
+ size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
+ + sizeof (struct GNUNET_TUN_TcpHeader)
+ + sizeof (struct GNUNET_MessageHeader) +
+ sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
+ mlen;
+ {
+ char buf[size] GNUNET_ALIGN;
+ struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
+ struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
+ struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
+ struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
+ msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
+ msg->size = htons (size);
+ tun->flags = htons (0);
+ tun->proto = htons (ETH_P_IPV4);
+ GNUNET_TUN_initialize_ipv4_header (ipv4,
+ IPPROTO_TCP,
+ sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
+ &ts->destination_ip.v4,
+ &ts->source_ip.v4);
+ *tcp = data->tcp_header;
+ tcp->source_port = htons (ts->destination_port);
+ tcp->destination_port = htons (ts->source_port);
+ GNUNET_TUN_calculate_tcp4_checksum (ipv4,
+ tcp,
+ &data[1],
+ mlen);
+ GNUNET_memcpy (&tcp[1],
+ &data[1],
+ mlen);
+ (void) GNUNET_HELPER_send (helper_handle,
+ msg,
+ GNUNET_YES,
+ NULL, NULL);
+ }
+ }
+ break;
+ case AF_INET6:
+ {
+ size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
+ + sizeof (struct GNUNET_TUN_TcpHeader)
+ + sizeof (struct GNUNET_MessageHeader) +
+ sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
+ mlen;
+ {
+ char buf[size] GNUNET_ALIGN;
+ struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
+ struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
+ struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
+ struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
+ msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
+ msg->size = htons (size);
+ tun->flags = htons (0);
+ tun->proto = htons (ETH_P_IPV6);
+ GNUNET_TUN_initialize_ipv6_header (ipv6,
+ IPPROTO_TCP,
+ sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
+ &ts->destination_ip.v6,
+ &ts->source_ip.v6);
+ *tcp = data->tcp_header;
+ tcp->source_port = htons (ts->destination_port);
+ tcp->destination_port = htons (ts->source_port);
+ GNUNET_TUN_calculate_tcp6_checksum (ipv6,
+ tcp,
+ &data[1],
+ mlen);
+ GNUNET_memcpy (&tcp[1],
+ &data[1],
+ mlen);
+ (void) GNUNET_HELPER_send (helper_handle,
+ msg,
+ GNUNET_YES,
+ NULL, NULL);
+ }
+ }
+ break;
+ }
+ GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
+ GNUNET_TIME_absolute_get ().abs_value_us);
+ GNUNET_CADET_receive_done (ts->channel);
+}
+
+
+/**
+ * Create a channel for @a ts to @a target at @a port
+ *
+ * @param ts channel state to create the channel for
+ * @param target peer to connect to
+ * @param port destination port
+ * @return the channel handle
+ */
+static struct GNUNET_CADET_Channel *
+create_channel (struct ChannelState *ts,
+ const struct GNUNET_PeerIdentity *target,
+ const struct GNUNET_HashCode *port)
+{
+ struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
+ GNUNET_MQ_hd_var_size (udp_back,
+ GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY,
+ struct GNUNET_EXIT_UdpReplyMessage,
+ ts),
+ GNUNET_MQ_hd_var_size (tcp_back,
+ GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN,
+ struct GNUNET_EXIT_TcpDataMessage,
+ ts),
+ GNUNET_MQ_hd_var_size (icmp_back,
+ GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN,
+ struct GNUNET_EXIT_IcmpToVPNMessage,
+ ts),
+ GNUNET_MQ_handler_end()
+ };
+
+ return GNUNET_CADET_channel_creatE (cadet_handle,
+ ts,
+ target,
+ port,
+ GNUNET_CADET_OPTION_DEFAULT,
+ NULL,
+ &channel_cleaner,
+ cadet_handlers);
+}
+
+
+/**
* Regex has found a potential exit peer for us; consider using it.
*
* @param cls the `struct ChannelState`
@@ -758,11 +1444,9 @@ handle_regex_result (void *cls,
"Creating tunnel to %s for destination %s!\n",
GNUNET_i2s (id),
print_channel_destination (&ts->destination));
- ts->channel = GNUNET_CADET_channel_create (cadet_handle,
- ts,
- id,
- &port,
- GNUNET_CADET_OPTION_DEFAULT);
+ ts->channel = create_channel (ts,
+ id,
+ &port);
}
@@ -795,12 +1479,10 @@ create_channel_to_destination (struct DestinationChannel *dt,
GNUNET_TUN_compute_service_cadet_port (&ts->destination.details.service_destination.service_descriptor,
ts->destination_port,
&cadet_port);
- ts->channel
- = GNUNET_CADET_channel_create (cadet_handle,
- ts,
- &dt->destination->details.service_destination.target,
- &cadet_port,
- GNUNET_CADET_OPTION_DEFAULT);
+ ts->channel = create_channel (ts,
+ &dt->destination->details.service_destination.target,
+ &cadet_port);
+
if (NULL == ts->channel)
{
GNUNET_break (0);
@@ -906,9 +1588,9 @@ route_packet (struct DestinationEntry *destination,
{
struct GNUNET_HashCode key;
struct ChannelState *ts;
- struct ChannelMessageQueueEntry *tnq;
size_t alen;
size_t mlen;
+ struct GNUNET_MQ_Envelope *env;
const struct GNUNET_TUN_UdpHeader *udp;
const struct GNUNET_TUN_TcpHeader *tcp;
const struct GNUNET_TUN_IcmpHeader *icmp;
@@ -1162,12 +1844,9 @@ route_packet (struct DestinationEntry *destination,
GNUNET_break (0);
return;
}
- tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
- tnq->len = mlen;
- tnq->msg = &tnq[1];
- usm = (struct GNUNET_EXIT_UdpServiceMessage *) &tnq[1];
- usm->header.size = htons ((uint16_t) mlen);
- usm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
+ env = GNUNET_MQ_msg_extra (usm,
+ payload_length - sizeof (struct GNUNET_TUN_UdpHeader),
+ GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
/* if the source port is below 32000, we assume it has a special
meaning; if not, we pick a random port (this is a heuristic) */
usm->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
@@ -1190,12 +1869,9 @@ route_packet (struct DestinationEntry *destination,
GNUNET_break (0);
return;
}
- tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
- tnq->len = mlen;
- tnq->msg = &tnq[1];
- uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1];
- uim->header.size = htons ((uint16_t) mlen);
- uim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
+ env = GNUNET_MQ_msg_extra (uim,
+ payload_length + alen - sizeof (struct GNUNET_TUN_UdpHeader),
+ GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
uim->af = htonl (destination->details.exit_destination.af);
uim->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
uim->destination_port = udp->destination_port;
@@ -1215,8 +1891,8 @@ route_packet (struct DestinationEntry *destination,
GNUNET_assert (0);
}
GNUNET_memcpy (payload,
- &udp[1],
- payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
+ &udp[1],
+ payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
}
break;
case IPPROTO_TCP:
@@ -1233,12 +1909,9 @@ route_packet (struct DestinationEntry *destination,
GNUNET_break (0);
return;
}
- tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
- tnq->len = mlen;
- tnq->msg = &tnq[1];
- tsm = (struct GNUNET_EXIT_TcpServiceStartMessage *) &tnq[1];
- tsm->header.size = htons ((uint16_t) mlen);
- tsm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
+ env = GNUNET_MQ_msg_extra (tsm,
+ payload_length - sizeof (struct GNUNET_TUN_TcpHeader),
+ GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
tsm->reserved = htonl (0);
tsm->tcp_header = *tcp;
GNUNET_memcpy (&tsm[1],
@@ -1259,12 +1932,9 @@ route_packet (struct DestinationEntry *destination,
GNUNET_break (0);
return;
}
- tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
- tnq->len = mlen;
- tnq->msg = &tnq[1];
- tim = (struct GNUNET_EXIT_TcpInternetStartMessage *) &tnq[1];
- tim->header.size = htons ((uint16_t) mlen);
- tim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
+ env = GNUNET_MQ_msg_extra (tim,
+ payload_length + alen - sizeof (struct GNUNET_TUN_TcpHeader),
+ GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
tim->af = htonl (destination->details.exit_destination.af);
tim->tcp_header = *tcp;
switch (destination->details.exit_destination.af)
@@ -1283,8 +1953,8 @@ route_packet (struct DestinationEntry *destination,
GNUNET_assert (0);
}
GNUNET_memcpy (payload,
- &tcp[1],
- payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
+ &tcp[1],
+ payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
}
}
else
@@ -1298,17 +1968,14 @@ route_packet (struct DestinationEntry *destination,
GNUNET_break (0);
return;
}
- tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
- tnq->len = mlen;
- tnq->msg = &tnq[1];
- tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1];
- tdm->header.size = htons ((uint16_t) mlen);
- tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
+ env = GNUNET_MQ_msg_extra (tdm,
+ payload_length - sizeof (struct GNUNET_TUN_TcpHeader),
+ GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
tdm->reserved = htonl (0);
tdm->tcp_header = *tcp;
GNUNET_memcpy (&tdm[1],
- &tcp[1],
- payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
+ &tcp[1],
+ payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
}
break;
case IPPROTO_ICMP:
@@ -1317,19 +1984,6 @@ route_packet (struct DestinationEntry *destination,
{
struct GNUNET_EXIT_IcmpServiceMessage *ism;
- mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
- payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
- if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
- {
- GNUNET_break (0);
- return;
- }
- tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
- tnq->msg = &tnq[1];
- ism = (struct GNUNET_EXIT_IcmpServiceMessage *) &tnq[1];
- ism->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
- ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
- ism->icmp_header = *icmp;
/* ICMP protocol translation will be done by the receiver (as we don't know
the target AF); however, we still need to possibly discard the payload
depending on the ICMP type */
@@ -1384,12 +2038,20 @@ route_packet (struct DestinationEntry *destination,
/* update length calculations, as payload_length may have changed */
mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
- tnq->len = mlen;
- ism->header.size = htons ((uint16_t) mlen);
- /* finally, copy payload (if there is any left...) */
+ if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
+ {
+ GNUNET_break (0);
+ return;
+ }
+
+ env = GNUNET_MQ_msg_extra (ism,
+ payload_length - sizeof (struct GNUNET_TUN_IcmpHeader),
+ GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
+ ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
+ ism->icmp_header = *icmp;
GNUNET_memcpy (&ism[1],
- &icmp[1],
- payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
+ &icmp[1],
+ payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
}
else
{
@@ -1397,19 +2059,8 @@ route_packet (struct DestinationEntry *destination,
struct in_addr *ip4dst;
struct in6_addr *ip6dst;
void *payload;
+ uint8_t new_type;
- mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
- alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
- if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
- {
- GNUNET_break (0);
- return;
- }
- tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
- tnq->msg = &tnq[1];
- iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1];
- iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
- iim->icmp_header = *icmp;
/* Perform ICMP protocol-translation (depending on destination AF and source AF)
and throw away ICMP payload depending on ICMP message type */
switch (af)
@@ -1419,21 +2070,21 @@ route_packet (struct DestinationEntry *destination,
{
case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
if (destination->details.exit_destination.af == AF_INET6)
- iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
+ new_type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
break;
case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
if (destination->details.exit_destination.af == AF_INET6)
- iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
+ new_type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
break;
case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
if (destination->details.exit_destination.af == AF_INET6)
- iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
+ new_type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
/* throw away IP-payload, exit will have to make it up anyway */
payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
break;
case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
if (destination->details.exit_destination.af == AF_INET6)
- iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
+ new_type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
/* throw away IP-payload, exit will have to make it up anyway */
payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
break;
@@ -1443,7 +2094,6 @@ route_packet (struct DestinationEntry *destination,
GNUNET_STATISTICS_update (stats,
gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1, GNUNET_NO);
- GNUNET_free (tnq);
return;
}
/* throw away IP-payload, exit will have to make it up anyway */
@@ -1453,7 +2103,6 @@ route_packet (struct DestinationEntry *destination,
GNUNET_STATISTICS_update (stats,
gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1, GNUNET_NO);
- GNUNET_free (tnq);
return;
}
/* end of AF_INET */
@@ -1463,13 +2112,13 @@ route_packet (struct DestinationEntry *destination,
{
case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
if (destination->details.exit_destination.af == AF_INET6)
- iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
+ new_type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
/* throw away IP-payload, exit will have to make it up anyway */
payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
break;
case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
if (destination->details.exit_destination.af == AF_INET)
- iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
+ new_type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
/* throw away IP-payload, exit will have to make it up anyway */
payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
break;
@@ -1479,7 +2128,6 @@ route_packet (struct DestinationEntry *destination,
GNUNET_STATISTICS_update (stats,
gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1, GNUNET_NO);
- GNUNET_free (tnq);
return;
}
/* throw away IP-payload, exit will have to make it up anyway */
@@ -1491,7 +2139,6 @@ route_packet (struct DestinationEntry *destination,
GNUNET_STATISTICS_update (stats,
gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1, GNUNET_NO);
- GNUNET_free (tnq);
return;
}
/* throw away IP-payload, exit will have to make it up anyway */
@@ -1499,17 +2146,16 @@ route_packet (struct DestinationEntry *destination,
break;
case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
if (destination->details.exit_destination.af == AF_INET)
- iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
+ new_type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
break;
case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
if (destination->details.exit_destination.af == AF_INET)
- iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
+ new_type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
break;
default:
GNUNET_STATISTICS_update (stats,
gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1, GNUNET_NO);
- GNUNET_free (tnq);
return;
}
/* end of AF_INET6 */
@@ -1517,13 +2163,20 @@ route_packet (struct DestinationEntry *destination,
default:
GNUNET_assert (0);
}
+
/* update length calculations, as payload_length may have changed */
mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
- tnq->len = mlen;
- iim->header.size = htons ((uint16_t) mlen);
-
- /* need to tell destination ICMP protocol family! */
+ if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ env = GNUNET_MQ_msg_extra (iim,
+ alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader),
+ GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
+ iim->icmp_header = *icmp;
+ iim->icmp_header.type = new_type;
iim->af = htonl (destination->details.exit_destination.af);
switch (destination->details.exit_destination.af)
{
@@ -1541,8 +2194,8 @@ route_packet (struct DestinationEntry *destination,
GNUNET_assert (0);
}
GNUNET_memcpy (payload,
- &icmp[1],
- payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
+ &icmp[1],
+ payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
}
break;
default:
@@ -1551,7 +2204,8 @@ route_packet (struct DestinationEntry *destination,
break;
}
ts->is_established = GNUNET_YES;
- send_to_channel (tnq, ts);
+ send_to_channel (ts,
+ env);
}
@@ -1678,694 +2332,6 @@ message_token (void *cls,
/**
- * Synthesize a plausible ICMP payload for an ICMP error
- * response on the given channel.
- *
- * @param ts channel information
- * @param ipp IPv4 header to fill in (ICMP payload)
- * @param udp "UDP" header to fill in (ICMP payload); might actually
- * also be the first 8 bytes of the TCP header
- */
-static void
-make_up_icmpv4_payload (struct ChannelState *ts,
- struct GNUNET_TUN_IPv4Header *ipp,
- struct GNUNET_TUN_UdpHeader *udp)
-{
- GNUNET_TUN_initialize_ipv4_header (ipp,
- ts->protocol,
- sizeof (struct GNUNET_TUN_TcpHeader),
- &ts->source_ip.v4,
- &ts->destination_ip.v4);
- udp->source_port = htons (ts->source_port);
- udp->destination_port = htons (ts->destination_port);
- udp->len = htons (0);
- udp->crc = htons (0);
-}
-
-
-/**
- * Synthesize a plausible ICMP payload for an ICMP error
- * response on the given channel.
- *
- * @param ts channel information
- * @param ipp IPv6 header to fill in (ICMP payload)
- * @param udp "UDP" header to fill in (ICMP payload); might actually
- * also be the first 8 bytes of the TCP header
- */
-static void
-make_up_icmpv6_payload (struct ChannelState *ts,
- struct GNUNET_TUN_IPv6Header *ipp,
- struct GNUNET_TUN_UdpHeader *udp)
-{
- GNUNET_TUN_initialize_ipv6_header (ipp,
- ts->protocol,
- sizeof (struct GNUNET_TUN_TcpHeader),
- &ts->source_ip.v6,
- &ts->destination_ip.v6);
- udp->source_port = htons (ts->source_port);
- udp->destination_port = htons (ts->destination_port);
- udp->len = htons (0);
- udp->crc = htons (0);
-}
-
-
-/**
- * We got an ICMP packet back from the CADET channel. Pass it on to the
- * local virtual interface via the helper.
- *
- * @param cls closure, NULL
- * @param channel connection to the other end
- * @param channel_ctx pointer to our 'struct ChannelState *'
- * @param message the actual message
- * @return #GNUNET_OK to keep the connection open,
- * #GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-receive_icmp_back (void *cls,
- struct GNUNET_CADET_Channel *channel,
- void **channel_ctx,
- const struct GNUNET_MessageHeader *message)
-{
- struct ChannelState *ts = *channel_ctx;
- const struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
- size_t mlen;
-
- GNUNET_STATISTICS_update (stats,
- gettext_noop ("# ICMP packets received from cadet"),
- 1, GNUNET_NO);
- mlen = ntohs (message->size);
- if (mlen < sizeof (struct GNUNET_EXIT_IcmpToVPNMessage))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (NULL == ts->heap_node)
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (AF_UNSPEC == ts->af)
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- i2v = (const struct GNUNET_EXIT_IcmpToVPNMessage *) message;
- mlen -= sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
- {
- char sbuf[INET6_ADDRSTRLEN];
- char dbuf[INET6_ADDRSTRLEN];
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Received ICMP packet from cadet, sending %u bytes from %s -> %s via TUN\n",
- (unsigned int) mlen,
- inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
- inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
- }
- switch (ts->af)
- {
- case AF_INET:
- {
- size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
- + sizeof (struct GNUNET_TUN_IcmpHeader)
- + sizeof (struct GNUNET_MessageHeader) +
- sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
- mlen;
- {
- /* reserve some extra space in case we have an ICMP type here where
- we will need to make up the payload ourselves */
- char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
- struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
- struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
- struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
- struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
- msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
- tun->flags = htons (0);
- tun->proto = htons (ETH_P_IPV4);
- GNUNET_TUN_initialize_ipv4_header (ipv4,
- IPPROTO_ICMP,
- sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
- &ts->destination_ip.v4,
- &ts->source_ip.v4);
- *icmp = i2v->icmp_header;
- GNUNET_memcpy (&icmp[1],
- &i2v[1],
- mlen);
- /* For some ICMP types, we need to adjust (make up) the payload here.
- Also, depending on the AF used on the other side, we have to
- do ICMP PT (translate ICMP types) */
- switch (ntohl (i2v->af))
- {
- case AF_INET:
- switch (icmp->type)
- {
- case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
- case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
- break;
- case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
- case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
- case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
- {
- struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
- struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
-
- if (mlen != 0)
- {
- /* sender did not strip ICMP payload? */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
- GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
- make_up_icmpv4_payload (ts, ipp, udp);
- }
- break;
- default:
- GNUNET_break_op (0);
- GNUNET_STATISTICS_update (stats,
- gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
- 1, GNUNET_NO);
- return GNUNET_SYSERR;
- }
- /* end AF_INET */
- break;
- case AF_INET6:
- /* ICMP PT 6-to-4 and possibly making up payloads */
- switch (icmp->type)
- {
- case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
- icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
- {
- struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
- struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
-
- if (mlen != 0)
- {
- /* sender did not strip ICMP payload? */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
- GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
- make_up_icmpv4_payload (ts, ipp, udp);
- }
- break;
- case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
- icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
- {
- struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
- struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
-
- if (mlen != 0)
- {
- /* sender did not strip ICMP payload? */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
- GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
- make_up_icmpv4_payload (ts, ipp, udp);
- }
- break;
- case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
- case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
- GNUNET_STATISTICS_update (stats,
- gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
- 1, GNUNET_NO);
- return GNUNET_OK;
- case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
- icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
- break;
- case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
- icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
- break;
- default:
- GNUNET_break_op (0);
- GNUNET_STATISTICS_update (stats,
- gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
- 1, GNUNET_NO);
- return GNUNET_SYSERR;
- }
- /* end AF_INET6 */
- break;
- default:
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- msg->size = htons (size);
- GNUNET_TUN_calculate_icmp_checksum (icmp,
- &i2v[1],
- mlen);
- (void) GNUNET_HELPER_send (helper_handle,
- msg,
- GNUNET_YES,
- NULL, NULL);
- }
- }
- break;
- case AF_INET6:
- {
- size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
- + sizeof (struct GNUNET_TUN_IcmpHeader)
- + sizeof (struct GNUNET_MessageHeader) +
- sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
- mlen;
- {
- char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
- struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
- struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
- struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
- struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
- msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
- tun->flags = htons (0);
- tun->proto = htons (ETH_P_IPV6);
- GNUNET_TUN_initialize_ipv6_header (ipv6,
- IPPROTO_ICMPV6,
- sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
- &ts->destination_ip.v6,
- &ts->source_ip.v6);
- *icmp = i2v->icmp_header;
- GNUNET_memcpy (&icmp[1],
- &i2v[1],
- mlen);
-
- /* For some ICMP types, we need to adjust (make up) the payload here.
- Also, depending on the AF used on the other side, we have to
- do ICMP PT (translate ICMP types) */
- switch (ntohl (i2v->af))
- {
- case AF_INET:
- /* ICMP PT 4-to-6 and possibly making up payloads */
- switch (icmp->type)
- {
- case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
- icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
- break;
- case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
- icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
- break;
- case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
- icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
- {
- struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
- struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
-
- if (mlen != 0)
- {
- /* sender did not strip ICMP payload? */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
- GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
- make_up_icmpv6_payload (ts, ipp, udp);
- }
- break;
- case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
- icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
- {
- struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
- struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
-
- if (mlen != 0)
- {
- /* sender did not strip ICMP payload? */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
- GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
- make_up_icmpv6_payload (ts, ipp, udp);
- }
- break;
- case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
- GNUNET_STATISTICS_update (stats,
- gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
- 1, GNUNET_NO);
- return GNUNET_OK;
- default:
- GNUNET_break_op (0);
- GNUNET_STATISTICS_update (stats,
- gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
- 1, GNUNET_NO);
- return GNUNET_SYSERR;
- }
- /* end AF_INET */
- break;
- case AF_INET6:
- switch (icmp->type)
- {
- case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
- case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
- case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
- case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
- {
- struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
- struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
-
- if (mlen != 0)
- {
- /* sender did not strip ICMP payload? */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
- GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
- make_up_icmpv6_payload (ts, ipp, udp);
- }
- break;
- case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
- break;
- default:
- GNUNET_break_op (0);
- GNUNET_STATISTICS_update (stats,
- gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
- 1, GNUNET_NO);
- return GNUNET_SYSERR;
- }
- /* end AF_INET6 */
- break;
- default:
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- msg->size = htons (size);
- GNUNET_TUN_calculate_icmp_checksum (icmp,
- &i2v[1], mlen);
- (void) GNUNET_HELPER_send (helper_handle,
- msg,
- GNUNET_YES,
- NULL, NULL);
- }
- }
- break;
- default:
- GNUNET_assert (0);
- }
- GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
- GNUNET_TIME_absolute_get ().abs_value_us);
- GNUNET_CADET_receive_done (channel);
- return GNUNET_OK;
-}
-
-
-/**
- * We got a UDP packet back from the CADET channel. Pass it on to the
- * local virtual interface via the helper.
- *
- * @param cls closure, NULL
- * @param channel connection to the other end
- * @param channel_ctx pointer to our 'struct ChannelState *'
- * @param message the actual message
- * @return #GNUNET_OK to keep the connection open,
- * #GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-receive_udp_back (void *cls,
- struct GNUNET_CADET_Channel *channel,
- void **channel_ctx,
- const struct GNUNET_MessageHeader *message)
-{
- struct ChannelState *ts = *channel_ctx;
- const struct GNUNET_EXIT_UdpReplyMessage *reply;
- size_t mlen;
-
- GNUNET_STATISTICS_update (stats,
- gettext_noop ("# UDP packets received from cadet"),
- 1, GNUNET_NO);
- mlen = ntohs (message->size);
- if (mlen < sizeof (struct GNUNET_EXIT_UdpReplyMessage))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (NULL == ts->heap_node)
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (AF_UNSPEC == ts->af)
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message;
- mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage);
- {
- char sbuf[INET6_ADDRSTRLEN];
- char dbuf[INET6_ADDRSTRLEN];
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Received UDP reply from cadet, sending %u bytes from [%s]:%u -> [%s]:%u via TUN\n",
- (unsigned int) mlen,
- inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
- ts->destination_port,
- inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
- ts->source_port);
- }
- switch (ts->af)
- {
- case AF_INET:
- {
- size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
- + sizeof (struct GNUNET_TUN_UdpHeader)
- + sizeof (struct GNUNET_MessageHeader) +
- sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
- mlen;
- {
- char buf[size] GNUNET_ALIGN;
- struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
- struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
- struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
- struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
- msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
- msg->size = htons (size);
- tun->flags = htons (0);
- tun->proto = htons (ETH_P_IPV4);
- GNUNET_TUN_initialize_ipv4_header (ipv4,
- IPPROTO_UDP,
- sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
- &ts->destination_ip.v4,
- &ts->source_ip.v4);
- if (0 == ntohs (reply->source_port))
- udp->source_port = htons (ts->destination_port);
- else
- udp->source_port = reply->source_port;
- if (0 == ntohs (reply->destination_port))
- udp->destination_port = htons (ts->source_port);
- else
- udp->destination_port = reply->destination_port;
- udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
- GNUNET_TUN_calculate_udp4_checksum (ipv4,
- udp,
- &reply[1],
- mlen);
- GNUNET_memcpy (&udp[1],
- &reply[1],
- mlen);
- (void) GNUNET_HELPER_send (helper_handle,
- msg,
- GNUNET_YES,
- NULL, NULL);
- }
- }
- break;
- case AF_INET6:
- {
- size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
- + sizeof (struct GNUNET_TUN_UdpHeader)
- + sizeof (struct GNUNET_MessageHeader) +
- sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
- mlen;
- {
- char buf[size] GNUNET_ALIGN;
- struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
- struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
- struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
- struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
- msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
- msg->size = htons (size);
- tun->flags = htons (0);
- tun->proto = htons (ETH_P_IPV6);
- GNUNET_TUN_initialize_ipv6_header (ipv6,
- IPPROTO_UDP,
- sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
- &ts->destination_ip.v6,
- &ts->source_ip.v6);
- if (0 == ntohs (reply->source_port))
- udp->source_port = htons (ts->destination_port);
- else
- udp->source_port = reply->source_port;
- if (0 == ntohs (reply->destination_port))
- udp->destination_port = htons (ts->source_port);
- else
- udp->destination_port = reply->destination_port;
- udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
- GNUNET_TUN_calculate_udp6_checksum (ipv6,
- udp,
- &reply[1], mlen);
- GNUNET_memcpy (&udp[1],
- &reply[1],
- mlen);
- (void) GNUNET_HELPER_send (helper_handle,
- msg,
- GNUNET_YES,
- NULL, NULL);
- }
- }
- break;
- default:
- GNUNET_assert (0);
- }
- GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
- GNUNET_TIME_absolute_get ().abs_value_us);
- GNUNET_CADET_receive_done (channel);
- return GNUNET_OK;
-}
-
-
-/**
- * We got a TCP packet back from the CADET channel. Pass it on to the
- * local virtual interface via the helper.
- *
- * @param cls closure, NULL
- * @param channel connection to the other end
- * @param channel_ctx pointer to our `struct ChannelState *`
- * @param message the actual message
- * @return #GNUNET_OK to keep the connection open,
- * #GNUNET_SYSERR to close it (signal serious error)
- */
-static int
-receive_tcp_back (void *cls,
- struct GNUNET_CADET_Channel *channel,
- void **channel_ctx,
- const struct GNUNET_MessageHeader *message)
-{
- struct ChannelState *ts = *channel_ctx;
- const struct GNUNET_EXIT_TcpDataMessage *data;
- size_t mlen;
-
- GNUNET_STATISTICS_update (stats,
- gettext_noop ("# TCP packets received from cadet"),
- 1, GNUNET_NO);
- mlen = ntohs (message->size);
- if (mlen < sizeof (struct GNUNET_EXIT_TcpDataMessage))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (NULL == ts->heap_node)
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- data = (const struct GNUNET_EXIT_TcpDataMessage *) message;
- mlen -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
- {
- char sbuf[INET6_ADDRSTRLEN];
- char dbuf[INET6_ADDRSTRLEN];
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Received TCP reply from cadet, sending %u bytes from [%s]:%u -> [%s]:%u via TUN\n",
- (unsigned int) mlen,
- inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
- ts->destination_port,
- inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
- ts->source_port);
- }
- if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- switch (ts->af)
- {
- case AF_INET:
- {
- size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
- + sizeof (struct GNUNET_TUN_TcpHeader)
- + sizeof (struct GNUNET_MessageHeader) +
- sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
- mlen;
- {
- char buf[size] GNUNET_ALIGN;
- struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
- struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
- struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
- struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
- msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
- msg->size = htons (size);
- tun->flags = htons (0);
- tun->proto = htons (ETH_P_IPV4);
- GNUNET_TUN_initialize_ipv4_header (ipv4,
- IPPROTO_TCP,
- sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
- &ts->destination_ip.v4,
- &ts->source_ip.v4);
- *tcp = data->tcp_header;
- tcp->source_port = htons (ts->destination_port);
- tcp->destination_port = htons (ts->source_port);
- GNUNET_TUN_calculate_tcp4_checksum (ipv4,
- tcp,
- &data[1],
- mlen);
- GNUNET_memcpy (&tcp[1],
- &data[1],
- mlen);
- (void) GNUNET_HELPER_send (helper_handle,
- msg,
- GNUNET_YES,
- NULL, NULL);
- }
- }
- break;
- case AF_INET6:
- {
- size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
- + sizeof (struct GNUNET_TUN_TcpHeader)
- + sizeof (struct GNUNET_MessageHeader) +
- sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
- mlen;
- {
- char buf[size] GNUNET_ALIGN;
- struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
- struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
- struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
- struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
- msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
- msg->size = htons (size);
- tun->flags = htons (0);
- tun->proto = htons (ETH_P_IPV6);
- GNUNET_TUN_initialize_ipv6_header (ipv6,
- IPPROTO_TCP,
- sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
- &ts->destination_ip.v6,
- &ts->source_ip.v6);
- *tcp = data->tcp_header;
- tcp->source_port = htons (ts->destination_port);
- tcp->destination_port = htons (ts->source_port);
- GNUNET_TUN_calculate_tcp6_checksum (ipv6,
- tcp,
- &data[1],
- mlen);
- GNUNET_memcpy (&tcp[1],
- &data[1],
- mlen);
- (void) GNUNET_HELPER_send (helper_handle,
- msg,
- GNUNET_YES,
- NULL, NULL);
- }
- }
- break;
- }
- GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
- GNUNET_TIME_absolute_get ().abs_value_us);
- GNUNET_CADET_receive_done (channel);
- return GNUNET_OK;
-}
-
-
-/**
* Allocate an IPv4 address from the range of the channel
* for a new redirection.
*
@@ -2813,29 +2779,6 @@ handle_client_redirect_to_service (void *cls,
}
-/**
- * Function called whenever a channel is destroyed. Should clean up
- * any associated state.
- *
- * @param cls closure (set from #GNUNET_CADET_connect)
- * @param channel connection to the other end (henceforth invalid)
- * @param channel_ctx place where local state associated
- * with the channel is stored (our `struct ChannelState`)
- */
-static void
-channel_cleaner (void *cls,
- const struct GNUNET_CADET_Channel *channel,
- void *channel_ctx)
-{
- struct ChannelState *ts = channel_ctx;
-
- ts->channel = NULL; /* we must not call GNUNET_CADET_channel_destroy() anymore */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "CADET notified us about death of channel to `%s'\n",
- print_channel_destination (&ts->destination));
- free_channel_state (ts);
-}
-
/**
* Free memory occupied by an entry in the destination map.
@@ -2984,12 +2927,6 @@ run (void *cls,
const struct GNUNET_CONFIGURATION_Handle *cfg_,
struct GNUNET_SERVICE_Handle *service)
{
- static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
- { &receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, 0},
- { &receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, 0},
- { &receive_icmp_back, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN, 0},
- {NULL, 0, 0}
- };
char *ifname;
char *ipv6addr;
char *ipv6prefix_s;
@@ -3130,11 +3067,7 @@ run (void *cls,
}
vpn_argv[6] = NULL;
- cadet_handle
- = GNUNET_CADET_connect (cfg_,
- NULL,
- &channel_cleaner,
- cadet_handlers);
+ cadet_handle = GNUNET_CADET_connecT (cfg_);
// FIXME never opens ports???
helper_handle = GNUNET_HELPER_start (GNUNET_NO,
"gnunet-helper-vpn", vpn_argv,