migrate secretsharing to new service API
[oweals/gnunet.git] / src / tun / tun.c
index 4c2ddf07aa08faceeff3372cee8d6cb60432728b..b55de1ea9487f6c15e2a9a02df3dd414972cc3f7 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     (C) 2010, 2011, 2012 Christian Grothoff
+     Copyright (C) 2010, 2011, 2012 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
@@ -14,8 +14,8 @@
 
      You should have received a copy of the GNU General Public License
      along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
 */
 
 /**
@@ -30,7 +30,7 @@
 /**
  * IP TTL we use for packets that we assemble (8 bit unsigned integer)
  */
-#define FRESH_TTL 255
+#define FRESH_TTL 64
 
 
 /**
@@ -49,18 +49,16 @@ GNUNET_TUN_initialize_ipv4_header (struct GNUNET_TUN_IPv4Header *ip,
                                   const struct in_addr *src,
                                   const struct in_addr *dst)
 {
+  GNUNET_assert (20 == sizeof (struct GNUNET_TUN_IPv4Header));
   GNUNET_assert (payload_length <= UINT16_MAX - sizeof (struct GNUNET_TUN_IPv4Header));
+  memset (ip, 0, sizeof (struct GNUNET_TUN_IPv4Header));
   ip->header_length =  sizeof (struct GNUNET_TUN_IPv4Header) / 4;
   ip->version = 4;
-  ip->diff_serv = 0;
   ip->total_length = htons (sizeof (struct GNUNET_TUN_IPv4Header) + payload_length);
-  ip->identification = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 
+  ip->identification = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
                                                            65536);
-  ip->flags = 0;
-  ip->fragmentation_offset = 0;
   ip->ttl = FRESH_TTL;
   ip->protocol = protocol;
-  ip->checksum = 0;
   ip->source_address = *src;
   ip->destination_address = *dst;
   ip->checksum = GNUNET_CRYPTO_crc16_n (ip, sizeof (struct GNUNET_TUN_IPv4Header));
@@ -72,7 +70,7 @@ GNUNET_TUN_initialize_ipv4_header (struct GNUNET_TUN_IPv4Header *ip,
  *
  * @param ip header to initialize
  * @param protocol protocol to use (i.e. IPPROTO_UDP), technically "next_header" for IPv6
- * @param payload_length number of bytes of payload that follow (excluding IPv4 header)
+ * @param payload_length number of bytes of payload that follow (excluding IPv6 header)
  * @param src source IP address to use
  * @param dst destination IP address to use
  */
@@ -83,23 +81,22 @@ GNUNET_TUN_initialize_ipv6_header (struct GNUNET_TUN_IPv6Header *ip,
                                   const struct in6_addr *src,
                                   const struct in6_addr *dst)
 {
+  GNUNET_assert (40 == sizeof (struct GNUNET_TUN_IPv6Header));
   GNUNET_assert (payload_length <= UINT16_MAX - sizeof (struct GNUNET_TUN_IPv6Header));
-  ip->traffic_class_h = 0;
+  memset (ip, 0, sizeof (struct GNUNET_TUN_IPv6Header));
   ip->version = 6;
-  ip->traffic_class_l = 0;
-  ip->flow_label = 0;
   ip->next_header = protocol;
-  ip->payload_length = htons ((uint16_t) (payload_length + sizeof (struct GNUNET_TUN_IPv6Header)));
+  ip->payload_length = htons ((uint16_t) payload_length);
   ip->hop_limit = FRESH_TTL;
   ip->destination_address = *dst;
-  ip->source_address = *src;  
+  ip->source_address = *src;
 }
 
 
 /**
  * Calculate IPv4 TCP checksum.
  *
- * @param ipv4 header fully initialized
+ * @param ip 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
@@ -111,18 +108,21 @@ GNUNET_TUN_calculate_tcp4_checksum (const struct GNUNET_TUN_IPv4Header *ip,
                                    uint16_t payload_length)
 {
   uint32_t sum;
-  uint32_t tmp;
+  uint16_t tmp;
 
+  GNUNET_assert (20 == sizeof (struct GNUNET_TUN_TcpHeader));
   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, 
+  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));
+  tmp = htons (IPPROTO_TCP);
+  sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint16_t));
+  tmp = htons (payload_length + sizeof (struct GNUNET_TUN_TcpHeader));
+  sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint16_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);
@@ -132,7 +132,7 @@ GNUNET_TUN_calculate_tcp4_checksum (const struct GNUNET_TUN_IPv4Header *ip,
 /**
  * Calculate IPv6 TCP checksum.
  *
- * @param ipv6 header fully initialized
+ * @param ip ipv6 header fully initialized
  * @param tcp header (initialized except for CRC)
  * @param payload the TCP payload
  * @param payload_length number of bytes of TCP payload
@@ -146,7 +146,8 @@ GNUNET_TUN_calculate_tcp6_checksum (const struct GNUNET_TUN_IPv6Header *ip,
   uint32_t sum;
   uint32_t tmp;
 
-  GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_IPv6Header) + sizeof (struct GNUNET_TUN_TcpHeader) ==
+  GNUNET_assert (20 == sizeof (struct GNUNET_TUN_TcpHeader));
+  GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_TcpHeader) ==
                 ntohs (ip->payload_length));
   GNUNET_assert (IPPROTO_TCP == ip->next_header);
   tcp->crc = 0;
@@ -165,7 +166,7 @@ GNUNET_TUN_calculate_tcp6_checksum (const struct GNUNET_TUN_IPv6Header *ip,
 /**
  * Calculate IPv4 UDP checksum.
  *
- * @param ipv4 header fully initialized
+ * @param ip 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
@@ -179,26 +180,27 @@ GNUNET_TUN_calculate_udp4_checksum (const struct GNUNET_TUN_IPv4Header *ip,
   uint32_t sum;
   uint16_t tmp;
 
+  GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
   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, 
+  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, 
+  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, 
+  sum = GNUNET_CRYPTO_crc16_step (sum,
+                                 &tmp,
                                  sizeof (uint16_t));
-  sum = GNUNET_CRYPTO_crc16_step (sum, 
-                                 udp, 
+  sum = GNUNET_CRYPTO_crc16_step (sum,
+                                 udp,
                                  sizeof (struct GNUNET_TUN_UdpHeader));
-  sum = GNUNET_CRYPTO_crc16_step (sum, 
+  sum = GNUNET_CRYPTO_crc16_step (sum,
                                  payload,
                                  payload_length);
   udp->crc = GNUNET_CRYPTO_crc16_finish (sum);
@@ -208,7 +210,7 @@ GNUNET_TUN_calculate_udp4_checksum (const struct GNUNET_TUN_IPv4Header *ip,
 /**
  * Calculate IPv6 UDP checksum.
  *
- * @param ipv6 header fully initialized
+ * @param ip 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
@@ -222,7 +224,7 @@ GNUNET_TUN_calculate_udp6_checksum (const struct GNUNET_TUN_IPv6Header *ip,
   uint32_t sum;
   uint32_t tmp;
 
-  GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_IPv6Header) + sizeof (struct GNUNET_TUN_UdpHeader) ==
+  GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_UdpHeader) ==
                 ntohs (ip->payload_length));
   GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_UdpHeader) ==
                 ntohs (udp->len));
@@ -256,6 +258,7 @@ GNUNET_TUN_calculate_icmp_checksum (struct GNUNET_TUN_IcmpHeader *icmp,
 {
   uint32_t sum;
 
+  GNUNET_assert (8 == sizeof (struct GNUNET_TUN_IcmpHeader));
   icmp->crc = 0;
   sum = GNUNET_CRYPTO_crc16_step (0,
                                  icmp,
@@ -265,4 +268,44 @@ GNUNET_TUN_calculate_icmp_checksum (struct GNUNET_TUN_IcmpHeader *icmp,
 }
 
 
+/**
+ * Check if two sockaddrs are equal.
+ *
+ * @param sa one address
+ * @param sb another address
+ * @param include_port also check ports
+ * @return #GNUNET_YES if they are equal
+ */
+int
+GNUNET_TUN_sockaddr_cmp (const struct sockaddr *sa,
+                         const struct sockaddr *sb,
+                         int include_port)
+{
+  if (sa->sa_family != sb->sa_family)
+    return GNUNET_NO;
+
+  switch (sa->sa_family)
+  {
+  case AF_INET:
+    {
+      const struct sockaddr_in *sa4 = (const struct sockaddr_in *) sa;
+      const struct sockaddr_in *sb4 = (const struct sockaddr_in *) sb;
+      return (sa4->sin_addr.s_addr == sb4->sin_addr.s_addr);
+    }
+  case AF_INET6:
+    {
+      const struct sockaddr_in6 *sa6 = (const struct sockaddr_in6 *) sa;
+      const struct sockaddr_in6 *sb6 = (const struct sockaddr_in6 *) sb;
+
+      return (0 == memcmp(&sa6->sin6_addr,
+                          &sb6->sin6_addr,
+                          sizeof (struct in6_addr)));
+    }
+  default:
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+}
+
+
 /* end of tun.c */