From 57c6b46b6b90ca4d894cb032aff46567d5210654 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 21 Jan 2012 15:11:58 +0000 Subject: [PATCH] -add support for sending ICMP packets to service/internet --- src/vpn/gnunet-service-vpn.c | 95 ++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/src/vpn/gnunet-service-vpn.c b/src/vpn/gnunet-service-vpn.c index 8925c034f..47a6a7dc4 100644 --- a/src/vpn/gnunet-service-vpn.c +++ b/src/vpn/gnunet-service-vpn.c @@ -878,6 +878,7 @@ route_packet (struct DestinationEntry *destination, int is_new; const struct GNUNET_TUN_UdpHeader *udp; const struct GNUNET_TUN_TcpHeader *tcp; + const struct GNUNET_TUN_IcmpHeader *icmp; uint16_t spt; uint16_t dpt; @@ -923,6 +924,26 @@ route_packet (struct DestinationEntry *destination, &key); } break; + case IPPROTO_ICMP: + { + if (payload_length < sizeof (struct GNUNET_TUN_IcmpHeader)) + { + /* blame kernel? */ + GNUNET_break (0); + return; + } + icmp = payload; + spt = 0; + dpt = 0; + get_tunnel_key_from_ips (af, + IPPROTO_ICMP, + source_ip, + 0, + destination_ip, + 0, + &key); + } + break; default: GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Protocol %u not supported, dropping\n"), @@ -1204,6 +1225,80 @@ route_packet (struct DestinationEntry *destination, payload_length - sizeof (struct GNUNET_TUN_TcpHeader)); } break; + case IPPROTO_ICMP: + if (destination->is_service) + { + 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 TunnelMessageQueueEntry) + mlen); + tnq->len = mlen; + tnq->msg = &tnq[1]; + ism = (struct GNUNET_EXIT_IcmpServiceMessage *) &tnq[1]; + ism->header.size = htons ((uint16_t) mlen); + ism->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE); + ism->af = htonl (af); /* need to tell destination ICMP protocol family! */ + ism->service_descriptor = destination->details.service_destination.service_descriptor; + ism->icmp_header = *icmp; + memcpy (&ism[1], + &icmp[1], + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader)); + } + else + { + struct GNUNET_EXIT_IcmpInternetMessage *iim; + struct in_addr *ip4dst; + struct in6_addr *ip6dst; + void *payload; + + 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 TunnelMessageQueueEntry) + + mlen); + tnq->len = mlen; + tnq->msg = &tnq[1]; + iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1]; + iim->header.size = htons ((uint16_t) mlen); + iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET); + iim->af = htonl (af); /* need to tell destination ICMP protocol family! */ + iim->icmp_header = *icmp; + if (af != destination->details.exit_destination.af) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("AF-translation for ICMP not implemented\n")); + return; + } + switch (destination->details.exit_destination.af) + { + case AF_INET: + ip4dst = (struct in_addr *) &iim[1]; + *ip4dst = destination->details.exit_destination.ip.v4; + payload = &ip4dst[1]; + break; + case AF_INET6: + ip6dst = (struct in6_addr *) &iim[1]; + *ip6dst = destination->details.exit_destination.ip.v6; + payload = &ip6dst[1]; + break; + default: + GNUNET_assert (0); + } + memcpy (payload, + &icmp[1], + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader)); + } + break; default: /* not supported above, how can we get here !? */ GNUNET_assert (0); -- 2.25.1