X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Ftun%2Ftun.c;h=b55de1ea9487f6c15e2a9a02df3dd414972cc3f7;hb=a015c3df2059a98a8692e7f2b06038e066bbc916;hp=4c2ddf07aa08faceeff3372cee8d6cb60432728b;hpb=5e442d9cf826adb58d4595722c7dd7b2532096c9;p=oweals%2Fgnunet.git diff --git a/src/tun/tun.c b/src/tun/tun.c index 4c2ddf07a..b55de1ea9 100644 --- a/src/tun/tun.c +++ b/src/tun/tun.c @@ -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 */