+ /* 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);