/**
* @file dns/gnunet-service-dns.c
+ * @brief service to intercept and modify DNS queries (and replies) of this system
* @author Christian Grothoff
*/
#include "platform.h"
{
char buf[reply_len];
size_t off;
- uint32_t udp_crc_sum;
+ struct GNUNET_TUN_IPv4Header ip4;
+ struct GNUNET_TUN_IPv6Header ip6;
/* first, GNUnet message header */
hdr = (struct GNUNET_MessageHeader*) buf;
}
/* now IP header */
- udp_crc_sum = 0;
switch (rr->src_addr.ss_family)
{
case AF_INET:
{
struct sockaddr_in *src = (struct sockaddr_in *) &rr->src_addr;
struct sockaddr_in *dst = (struct sockaddr_in *) &rr->dst_addr;
- struct GNUNET_TUN_IPv4Header ip;
spt = dst->sin_port;
dpt = src->sin_port;
- GNUNET_TUN_initialize_ipv4_header (&ip,
+ GNUNET_TUN_initialize_ipv4_header (&ip4,
IPPROTO_UDP,
reply_len - off - sizeof (struct GNUNET_TUN_IPv4Header),
&dst->sin_addr,
&src->sin_addr);
-
-
-
- udp_crc_sum = GNUNET_CRYPTO_crc16_step (udp_crc_sum,
- &ip.source_address,
- sizeof (struct in_addr) * 2);
- {
- uint16_t tmp;
-
- tmp = htons (IPPROTO_UDP);
- udp_crc_sum = GNUNET_CRYPTO_crc16_step (udp_crc_sum,
- &tmp,
- sizeof (uint16_t));
- tmp = htons (rr->payload_length + sizeof (struct GNUNET_TUN_UdpHeader));
- udp_crc_sum = GNUNET_CRYPTO_crc16_step (udp_crc_sum,
- &tmp,
- sizeof (uint16_t));
- }
- memcpy (&buf[off], &ip, sizeof (ip));
- off += sizeof (ip);
+ memcpy (&buf[off], &ip4, sizeof (ip4));
+ off += sizeof (ip4);
}
break;
case AF_INET6:
{
struct sockaddr_in6 *src = (struct sockaddr_in6 *) &rr->src_addr;
struct sockaddr_in6 *dst = (struct sockaddr_in6 *) &rr->dst_addr;
- struct GNUNET_TUN_IPv6Header ip;
spt = dst->sin6_port;
dpt = src->sin6_port;
- GNUNET_TUN_initialize_ipv6_header (&ip,
+ GNUNET_TUN_initialize_ipv6_header (&ip6,
IPPROTO_UDP,
reply_len - sizeof (struct GNUNET_TUN_IPv6Header),
&dst->sin6_addr,
&src->sin6_addr);
- {
- uint32_t tmp;
-
- tmp = htons (rr->payload_length + sizeof (struct GNUNET_TUN_UdpHeader));
- udp_crc_sum = GNUNET_CRYPTO_crc16_step (udp_crc_sum,
- &tmp,
- sizeof (uint32_t));
- tmp = htons (IPPROTO_UDP);
- udp_crc_sum = GNUNET_CRYPTO_crc16_step (udp_crc_sum,
- &tmp,
- sizeof (uint32_t));
- }
- memcpy (&buf[off], &ip, sizeof (ip));
- off += sizeof (ip);
+ memcpy (&buf[off], &ip6, sizeof (ip6));
+ off += sizeof (ip6);
}
break;
default:
udp.spt = spt;
udp.dpt = dpt;
udp.len = htons (reply_len - off);
- udp.crc = 0;
- udp_crc_sum = GNUNET_CRYPTO_crc16_step (udp_crc_sum,
- &udp,
- sizeof (udp));
- udp_crc_sum = GNUNET_CRYPTO_crc16_step (udp_crc_sum,
- rr->payload,
- rr->payload_length);
- udp.crc = GNUNET_CRYPTO_crc16_finish (udp_crc_sum);
+ if (AF_INET == rr->src_addr.ss_family)
+ GNUNET_TUN_calculate_udp4_checksum (&ip4,
+ &udp,
+ rr->payload,
+ rr->payload_length);
+ else
+ GNUNET_TUN_calculate_udp6_checksum (&ip6,
+ &udp,
+ rr->payload,
+ rr->payload_length);
memcpy (&buf[off], &udp, sizeof (udp));
off += sizeof (udp);
}
+
/* now DNS payload */
{
memcpy (&buf[off], rr->payload, rr->payload_length);
}
-/* end of gnunet-service-dns_new.c */
+/* end of gnunet-service-dns.c */
* TODO:
* - test
*
- * Code cleanup:
- * - factor out crc computations from DNS/EXIT/VPN into shared library?
- *
* Design:
* - which code should advertise services? the service model is right
* now a bit odd, especially as this code DOES the exit and knows
pkt4_udp->spt = htons (src_address->port);
pkt4_udp->dpt = htons (dst_address->port);
- pkt4_udp->crc = 0; /* Optional for IPv4 */
pkt4_udp->len = htons ((uint16_t) payload_length);
+ GNUNET_TUN_calculate_udp4_checksum (pkt4,
+ pkt4_udp,
+ payload, payload_length);
memcpy (&pkt4_udp[1], payload, payload_length);
}
break;
struct GNUNET_TUN_TcpHeader *pkt4_tcp = (struct GNUNET_TUN_TcpHeader *) &pkt4[1];
memcpy (pkt4_tcp, tcp_header, sizeof (struct GNUNET_TUN_TcpHeader));
- memcpy (&pkt4_tcp[1], payload, payload_length);
pkt4_tcp->spt = htons (src_address->port);
pkt4_tcp->dpt = htons (dst_address->port);
-
- pkt4_tcp->crc = 0;
- uint32_t sum = 0;
- sum = GNUNET_CRYPTO_crc16_step (sum,
- &pkt4->source_address,
- sizeof (struct in_addr) * 2);
- uint32_t tmp = htonl ((protocol << 16) | (0xffff & len));
- sum = GNUNET_CRYPTO_crc16_step (sum, & tmp, sizeof (uint32_t));
- sum = GNUNET_CRYPTO_crc16_step (sum, & pkt4_tcp, len);
- pkt4_tcp->crc = GNUNET_CRYPTO_crc16_finish (sum);
+ GNUNET_TUN_calculate_tcp4_checksum (pkt4,
+ pkt4_tcp,
+ payload,
+ payload_length);
+ memcpy (&pkt4_tcp[1], payload, payload_length);
}
break;
default:
{
struct GNUNET_TUN_UdpHeader *pkt6_udp = (struct GNUNET_TUN_UdpHeader *) &pkt6[1];
- memcpy (&pkt6[1], payload, payload_length);
- pkt6_udp->crc = 0;
pkt6_udp->spt = htons (src_address->port);
pkt6_udp->dpt = htons (dst_address->port);
pkt6_udp->len = htons ((uint16_t) payload_length);
-
- uint32_t sum = 0;
- sum = GNUNET_CRYPTO_crc16_step (sum,
- &pkt6->source_address,
- sizeof (struct in6_addr) * 2);
- uint32_t tmp = htons (len);
- sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
- tmp = htonl (pkt6->next_header);
- sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
- sum = GNUNET_CRYPTO_crc16_step (sum, pkt6_udp, len);
- pkt6_udp->crc = GNUNET_CRYPTO_crc16_finish (sum);
+ pkt6_udp->crc = 0;
+ GNUNET_TUN_calculate_udp6_checksum (pkt6,
+ pkt6_udp,
+ payload,
+ payload_length);
+ memcpy (&pkt6[1], payload, payload_length);
}
break;
case IPPROTO_TCP:
{
struct GNUNET_TUN_TcpHeader *pkt6_tcp = (struct GNUNET_TUN_TcpHeader *) pkt6;
-
+
+ /* memcpy first here as some TCP header fields are initialized this way! */
memcpy (pkt6_tcp, payload, payload_length);
pkt6_tcp->spt = htons (src_address->port);
pkt6_tcp->dpt = htons (dst_address->port);
const struct in6_addr *src,
const struct in6_addr *dst);
+/**
+ * Calculate IPv4 TCP checksum.
+ *
+ * @param ipv4 header fully initialized
+ * @param tcp TCP header (initialized except for CRC)
+ * @param payload the TCP payload
+ * @param payload_length number of bytes of TCP payload
+ */
+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 IPv6 TCP checksum.
*
* @param ipv6 header fully initialized
- * @param tcp header (initialized except for CRC)
+ * @param tcp TCP header (initialized except for CRC)
* @param payload the TCP payload
* @param payload_length number of bytes of TCP payload
*/
const void *payload,
uint16_t payload_length);
+/**
+ * Calculate IPv4 UDP checksum.
+ *
+ * @param ipv4 header fully initialized
+ * @param udp UDP header (initialized except for CRC)
+ * @param payload the UDP payload
+ * @param payload_length number of bytes of UDP payload
+ */
+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 IPv6 UDP checksum.
+ *
+ * @param ipv6 header fully initialized
+ * @param udp UDP header (initialized except for CRC)
+ * @param payload the UDP payload
+ * @param payload_length number of bytes of UDP payload
+ */
+void
+GNUNET_TUN_calculate_udp6_checksum (const struct GNUNET_TUN_IPv6Header *ip,
+ struct GNUNET_TUN_UdpHeader *udp,
+ const void *payload,
+ uint16_t payload_length);
+
#endif
*/
/**
- * @file tun/tun.
+ * @file tun/tun.c
* @brief standard IP calculations for TUN interaction
* @author Philipp Toelke
* @author Christian Grothoff
*/
#define FRESH_TTL 255
+
/**
* Initialize an IPv4 header.
*
}
+/**
+ * Calculate IPv4 TCP checksum.
+ *
+ * @param ipv4 header fully initialized
+ * @param tcp TCP header (initialized except for CRC)
+ * @param payload the TCP payload
+ * @param payload_length number of bytes of TCP payload
+ */
+void
+GNUNET_TUN_calculate_tcp4_checksum (const struct GNUNET_TUN_IPv4Header *ip,
+ struct GNUNET_TUN_TcpHeader *tcp,
+ const void *payload,
+ uint16_t payload_length)
+{
+ uint32_t sum;
+ uint32_t tmp;
+
+ GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_IPv4Header) + sizeof (struct GNUNET_TUN_TcpHeader) ==
+ ntohs (ip->total_length));
+ GNUNET_assert (IPPROTO_TCP == ip->protocol);
+
+ tcp->crc = 0;
+ sum = GNUNET_CRYPTO_crc16_step (0,
+ &ip->source_address,
+ sizeof (struct in_addr) * 2);
+ tmp = htonl ((IPPROTO_TCP << 16) | (payload_length + sizeof (struct GNUNET_TUN_TcpHeader)));
+ sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
+ sum = GNUNET_CRYPTO_crc16_step (sum, tcp, sizeof (struct GNUNET_TUN_TcpHeader));
+ sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length);
+ tcp->crc = GNUNET_CRYPTO_crc16_finish (sum);
+}
+
+
/**
* Calculate IPv6 TCP checksum.
*
GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_IPv6Header) + sizeof (struct GNUNET_TUN_TcpHeader) ==
ntohs (ip->payload_length));
+ GNUNET_assert (IPPROTO_TCP == ip->next_header);
tcp->crc = 0;
sum = GNUNET_CRYPTO_crc16_step (0, &ip->source_address, 2 * sizeof (struct in6_addr));
tmp = htonl (sizeof (struct GNUNET_TUN_TcpHeader) + payload_length);
}
+/**
+ * Calculate IPv4 UDP checksum.
+ *
+ * @param ipv4 header fully initialized
+ * @param udp UDP header (initialized except for CRC)
+ * @param payload the UDP payload
+ * @param payload_length number of bytes of UDP payload
+ */
+void
+GNUNET_TUN_calculate_udp4_checksum (const struct GNUNET_TUN_IPv4Header *ip,
+ struct GNUNET_TUN_UdpHeader *udp,
+ const void *payload,
+ uint16_t payload_length)
+{
+ uint32_t sum;
+ uint16_t tmp;
+
+ GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_IPv4Header) + sizeof (struct GNUNET_TUN_UdpHeader) ==
+ ntohs (ip->total_length));
+ GNUNET_assert (IPPROTO_UDP == ip->protocol);
+
+ udp->crc = 0; /* technically optional, but we calculate it anyway, just to be sure */
+ sum = GNUNET_CRYPTO_crc16_step (0,
+ &ip->source_address,
+ sizeof (struct in_addr) * 2);
+ tmp = htons (IPPROTO_UDP);
+ sum = GNUNET_CRYPTO_crc16_step (sum,
+ &tmp,
+ sizeof (uint16_t));
+ tmp = htons (sizeof (struct GNUNET_TUN_UdpHeader) + payload_length);
+ sum = GNUNET_CRYPTO_crc16_step (sum,
+ &tmp,
+ sizeof (uint16_t));
+ sum = GNUNET_CRYPTO_crc16_step (sum,
+ udp,
+ sizeof (struct GNUNET_TUN_UdpHeader));
+ sum = GNUNET_CRYPTO_crc16_step (sum,
+ payload,
+ payload_length);
+ udp->crc = GNUNET_CRYPTO_crc16_finish (sum);
+}
+
+
+/**
+ * Calculate IPv6 UDP checksum.
+ *
+ * @param ipv6 header fully initialized
+ * @param udp UDP header (initialized except for CRC)
+ * @param payload the UDP payload
+ * @param payload_length number of bytes of UDP payload
+ */
+void
+GNUNET_TUN_calculate_udp6_checksum (const struct GNUNET_TUN_IPv6Header *ip,
+ struct GNUNET_TUN_UdpHeader *udp,
+ const void *payload,
+ uint16_t payload_length)
+{
+ uint32_t sum;
+ uint32_t tmp;
+
+ GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_IPv6Header) + sizeof (struct GNUNET_TUN_UdpHeader) ==
+ ntohs (ip->payload_length));
+ GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_UdpHeader) ==
+ ntohs (udp->len));
+ GNUNET_assert (IPPROTO_UDP == ip->next_header);
+
+ udp->crc = 0;
+ sum = GNUNET_CRYPTO_crc16_step (0,
+ &ip->source_address,
+ sizeof (struct in6_addr) * 2);
+ tmp = htons (sizeof (struct GNUNET_TUN_UdpHeader) + payload_length); /* aka udp->len */
+ sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
+ tmp = htons (ip->next_header);
+ sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
+ sum = GNUNET_CRYPTO_crc16_step (sum, udp, sizeof (struct GNUNET_TUN_UdpHeader));
+ sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length);
+ udp->crc = GNUNET_CRYPTO_crc16_finish (sum);
+}
+
/* end of tun.c */
*
* Features:
* - add back ICMP support (especially needed for IPv6)
- *
- * Code cleanup:
- * - consider moving IP-header building / checksumming code into shared library
- * with dns/exit/vpn (libgnunettun_tcpip?)
*/
#include "platform.h"
#include "gnunet_util_lib.h"
else
udp->dpt = reply->destination_port;
udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
- udp->crc = 0; // FIXME: optional, but we might want to calculate this one anyway
+ GNUNET_TUN_calculate_udp4_checksum (ipv4,
+ udp,
+ &reply[1],
+ mlen);
memcpy (&udp[1],
&reply[1],
mlen);
msg->size = htons (size);
tun->flags = htons (0);
tun->proto = htons (ETH_P_IPV6);
- ipv6->traffic_class_h = 0;
- ipv6->version = 6;
- ipv6->traffic_class_l = 0;
- ipv6->flow_label = 0;
- ipv6->payload_length = htons (sizeof (struct GNUNET_TUN_UdpHeader) + sizeof (struct GNUNET_TUN_IPv6Header) + mlen);
- ipv6->next_header = IPPROTO_UDP;
- ipv6->hop_limit = 255;
- ipv6->source_address = ts->destination_ip.v6;
- ipv6->destination_address = ts->source_ip.v6;
+ 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->spt = htons (ts->destination_port);
else
else
udp->dpt = reply->destination_port;
udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
- udp->crc = 0;
+ GNUNET_TUN_calculate_udp6_checksum (ipv6,
+ udp,
+ &reply[1], mlen);
memcpy (&udp[1],
&reply[1],
mlen);
- {
- uint32_t sum = 0;
- sum =
- GNUNET_CRYPTO_crc16_step (sum, &ipv6->source_address,
- sizeof (struct in6_addr) * 2);
- uint32_t tmp = udp->len;
- sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
- tmp = htons (IPPROTO_UDP);
- sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
- sum = GNUNET_CRYPTO_crc16_step (sum,
- udp,
- ntohs (udp->len));
- udp->crc = GNUNET_CRYPTO_crc16_finish (sum);
- }
(void) GNUNET_HELPER_send (helper_handle,
msg,
GNUNET_YES,
*tcp = data->tcp_header;
tcp->spt = htons (ts->destination_port);
tcp->dpt = htons (ts->source_port);
- tcp->crc = 0;
+ GNUNET_TUN_calculate_tcp4_checksum (ipv4,
+ tcp,
+ &data[1],
+ mlen);
memcpy (&tcp[1],
&data[1],
mlen);
- {
- uint32_t sum = 0;
- uint32_t tmp;
-
- sum = GNUNET_CRYPTO_crc16_step (sum,
- &ipv4->source_address,
- 2 * sizeof (struct in_addr));
- tmp = htonl ((IPPROTO_TCP << 16) | (mlen + sizeof (struct GNUNET_TUN_TcpHeader)));
- sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
- sum = GNUNET_CRYPTO_crc16_step (sum, tcp, mlen + sizeof (struct GNUNET_TUN_TcpHeader));
- tcp->crc = GNUNET_CRYPTO_crc16_finish (sum);
- }
(void) GNUNET_HELPER_send (helper_handle,
msg,
GNUNET_YES,