2 This file is part of GNUnet.
3 (C) 2010, 2011, 2012 Christian Grothoff
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
23 * @brief standard IP calculations for TUN interaction
24 * @author Philipp Toelke
25 * @author Christian Grothoff
28 #include "gnunet_tun_lib.h"
31 * IP TTL we use for packets that we assemble (8 bit unsigned integer)
37 * Initialize an IPv4 header.
39 * @param ip header to initialize
40 * @param protocol protocol to use (i.e. IPPROTO_UDP)
41 * @param payload_length number of bytes of payload that follow (excluding IPv4 header)
42 * @param src source IP address to use
43 * @param dst destination IP address to use
46 GNUNET_TUN_initialize_ipv4_header (struct GNUNET_TUN_IPv4Header *ip,
48 uint16_t payload_length,
49 const struct in_addr *src,
50 const struct in_addr *dst)
52 GNUNET_assert (payload_length <= UINT16_MAX - sizeof (struct GNUNET_TUN_IPv4Header));
53 memset (ip, 0, sizeof (struct GNUNET_TUN_IPv4Header));
54 ip->header_length = sizeof (struct GNUNET_TUN_IPv4Header) / 4;
56 ip->total_length = htons (sizeof (struct GNUNET_TUN_IPv4Header) + payload_length);
57 ip->identification = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
60 ip->protocol = protocol;
61 ip->source_address = *src;
62 ip->destination_address = *dst;
63 ip->checksum = GNUNET_CRYPTO_crc16_n (ip, sizeof (struct GNUNET_TUN_IPv4Header));
68 * Initialize an IPv6 header.
70 * @param ip header to initialize
71 * @param protocol protocol to use (i.e. IPPROTO_UDP), technically "next_header" for IPv6
72 * @param payload_length number of bytes of payload that follow (excluding IPv4 header)
73 * @param src source IP address to use
74 * @param dst destination IP address to use
77 GNUNET_TUN_initialize_ipv6_header (struct GNUNET_TUN_IPv6Header *ip,
79 uint16_t payload_length,
80 const struct in6_addr *src,
81 const struct in6_addr *dst)
83 GNUNET_assert (payload_length <= UINT16_MAX - sizeof (struct GNUNET_TUN_IPv6Header));
84 memset (ip, 0, sizeof (struct GNUNET_TUN_IPv6Header));
86 ip->next_header = protocol;
87 ip->payload_length = htons ((uint16_t) payload_length);
88 ip->hop_limit = FRESH_TTL;
89 ip->destination_address = *dst;
90 ip->source_address = *src;
95 * Calculate IPv4 TCP checksum.
97 * @param ip ipv4 header fully initialized
98 * @param tcp TCP header (initialized except for CRC)
99 * @param payload the TCP payload
100 * @param payload_length number of bytes of TCP payload
103 GNUNET_TUN_calculate_tcp4_checksum (const struct GNUNET_TUN_IPv4Header *ip,
104 struct GNUNET_TUN_TcpHeader *tcp,
106 uint16_t payload_length)
111 GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_IPv4Header) + sizeof (struct GNUNET_TUN_TcpHeader) ==
112 ntohs (ip->total_length));
113 GNUNET_assert (IPPROTO_TCP == ip->protocol);
116 sum = GNUNET_CRYPTO_crc16_step (0,
118 sizeof (struct in_addr) * 2);
119 tmp = htonl ((IPPROTO_TCP << 16) | (payload_length + sizeof (struct GNUNET_TUN_TcpHeader)));
120 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
121 sum = GNUNET_CRYPTO_crc16_step (sum, tcp, sizeof (struct GNUNET_TUN_TcpHeader));
122 sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length);
123 tcp->crc = GNUNET_CRYPTO_crc16_finish (sum);
128 * Calculate IPv6 TCP checksum.
130 * @param ip ipv6 header fully initialized
131 * @param tcp header (initialized except for CRC)
132 * @param payload the TCP payload
133 * @param payload_length number of bytes of TCP payload
136 GNUNET_TUN_calculate_tcp6_checksum (const struct GNUNET_TUN_IPv6Header *ip,
137 struct GNUNET_TUN_TcpHeader *tcp,
139 uint16_t payload_length)
144 GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_TcpHeader) ==
145 ntohs (ip->payload_length));
146 GNUNET_assert (IPPROTO_TCP == ip->next_header);
148 sum = GNUNET_CRYPTO_crc16_step (0, &ip->source_address, 2 * sizeof (struct in6_addr));
149 tmp = htonl (sizeof (struct GNUNET_TUN_TcpHeader) + payload_length);
150 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
151 tmp = htonl (IPPROTO_TCP);
152 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
153 sum = GNUNET_CRYPTO_crc16_step (sum, tcp,
154 sizeof (struct GNUNET_TUN_TcpHeader));
155 sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length);
156 tcp->crc = GNUNET_CRYPTO_crc16_finish (sum);
161 * Calculate IPv4 UDP checksum.
163 * @param ip ipv4 header fully initialized
164 * @param udp UDP header (initialized except for CRC)
165 * @param payload the UDP payload
166 * @param payload_length number of bytes of UDP payload
169 GNUNET_TUN_calculate_udp4_checksum (const struct GNUNET_TUN_IPv4Header *ip,
170 struct GNUNET_TUN_UdpHeader *udp,
172 uint16_t payload_length)
177 GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_IPv4Header) + sizeof (struct GNUNET_TUN_UdpHeader) ==
178 ntohs (ip->total_length));
179 GNUNET_assert (IPPROTO_UDP == ip->protocol);
181 udp->crc = 0; /* technically optional, but we calculate it anyway, just to be sure */
182 sum = GNUNET_CRYPTO_crc16_step (0,
184 sizeof (struct in_addr) * 2);
185 tmp = htons (IPPROTO_UDP);
186 sum = GNUNET_CRYPTO_crc16_step (sum,
189 tmp = htons (sizeof (struct GNUNET_TUN_UdpHeader) + payload_length);
190 sum = GNUNET_CRYPTO_crc16_step (sum,
193 sum = GNUNET_CRYPTO_crc16_step (sum,
195 sizeof (struct GNUNET_TUN_UdpHeader));
196 sum = GNUNET_CRYPTO_crc16_step (sum,
199 udp->crc = GNUNET_CRYPTO_crc16_finish (sum);
204 * Calculate IPv6 UDP checksum.
206 * @param ip ipv6 header fully initialized
207 * @param udp UDP header (initialized except for CRC)
208 * @param payload the UDP payload
209 * @param payload_length number of bytes of UDP payload
212 GNUNET_TUN_calculate_udp6_checksum (const struct GNUNET_TUN_IPv6Header *ip,
213 struct GNUNET_TUN_UdpHeader *udp,
215 uint16_t payload_length)
220 GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_UdpHeader) ==
221 ntohs (ip->payload_length));
222 GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_UdpHeader) ==
224 GNUNET_assert (IPPROTO_UDP == ip->next_header);
227 sum = GNUNET_CRYPTO_crc16_step (0,
229 sizeof (struct in6_addr) * 2);
230 tmp = htons (sizeof (struct GNUNET_TUN_UdpHeader) + payload_length); /* aka udp->len */
231 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
232 tmp = htons (ip->next_header);
233 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
234 sum = GNUNET_CRYPTO_crc16_step (sum, udp, sizeof (struct GNUNET_TUN_UdpHeader));
235 sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length);
236 udp->crc = GNUNET_CRYPTO_crc16_finish (sum);
241 * Calculate ICMP checksum.
243 * @param icmp IMCP header (initialized except for CRC)
244 * @param payload the ICMP payload
245 * @param payload_length number of bytes of ICMP payload
248 GNUNET_TUN_calculate_icmp_checksum (struct GNUNET_TUN_IcmpHeader *icmp,
250 uint16_t payload_length)
255 sum = GNUNET_CRYPTO_crc16_step (0,
257 sizeof (struct GNUNET_TUN_IcmpHeader));
258 sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length);
259 icmp->crc = GNUNET_CRYPTO_crc16_finish (sum);