GNUnet  0.10.x
tun.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2010, 2011, 2012 Christian Grothoff
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
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  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 
33 #define FRESH_TTL 64
34 
35 
45 void
47  uint8_t protocol,
48  uint16_t payload_length,
49  const struct in_addr *src,
50  const struct in_addr *dst)
51 {
52  GNUNET_assert(20 == sizeof(struct GNUNET_TUN_IPv4Header));
53  GNUNET_assert(payload_length <=
54  UINT16_MAX - sizeof(struct GNUNET_TUN_IPv4Header));
55  memset(ip, 0, sizeof(struct GNUNET_TUN_IPv4Header));
56  ip->header_length = sizeof(struct GNUNET_TUN_IPv4Header) / 4;
57  ip->version = 4;
58  ip->total_length =
59  htons(sizeof(struct GNUNET_TUN_IPv4Header) + payload_length);
60  ip->identification =
62  ip->ttl = FRESH_TTL;
63  ip->protocol = protocol;
64  ip->source_address = *src;
65  ip->destination_address = *dst;
66  ip->checksum =
67  GNUNET_CRYPTO_crc16_n(ip, sizeof(struct GNUNET_TUN_IPv4Header));
68 }
69 
70 
80 void
82  uint8_t protocol,
83  uint16_t payload_length,
84  const struct in6_addr *src,
85  const struct in6_addr *dst)
86 {
87  GNUNET_assert(40 == sizeof(struct GNUNET_TUN_IPv6Header));
88  GNUNET_assert(payload_length <=
89  UINT16_MAX - sizeof(struct GNUNET_TUN_IPv6Header));
90  memset(ip, 0, sizeof(struct GNUNET_TUN_IPv6Header));
91  ip->version = 6;
92  ip->next_header = protocol;
93  ip->payload_length = htons((uint16_t)payload_length);
94  ip->hop_limit = FRESH_TTL;
95  ip->destination_address = *dst;
96  ip->source_address = *src;
97 }
98 
99 
108 void
110  struct GNUNET_TUN_TcpHeader *tcp,
111  const void *payload,
112  uint16_t payload_length)
113 {
114  uint32_t sum;
115  uint16_t tmp;
116 
117  GNUNET_assert(20 == sizeof(struct GNUNET_TUN_TcpHeader));
118  GNUNET_assert(payload_length + sizeof(struct GNUNET_TUN_IPv4Header) +
119  sizeof(struct GNUNET_TUN_TcpHeader) ==
120  ntohs(ip->total_length));
121  GNUNET_assert(IPPROTO_TCP == ip->protocol);
122 
123  tcp->crc = 0;
124  sum = GNUNET_CRYPTO_crc16_step(0,
125  &ip->source_address,
126  sizeof(struct in_addr) * 2);
127  tmp = htons(IPPROTO_TCP);
128  sum = GNUNET_CRYPTO_crc16_step(sum, &tmp, sizeof(uint16_t));
129  tmp = htons(payload_length + sizeof(struct GNUNET_TUN_TcpHeader));
130  sum = GNUNET_CRYPTO_crc16_step(sum, &tmp, sizeof(uint16_t));
131  sum =
132  GNUNET_CRYPTO_crc16_step(sum, tcp, sizeof(struct GNUNET_TUN_TcpHeader));
133  sum = GNUNET_CRYPTO_crc16_step(sum, payload, payload_length);
134  tcp->crc = GNUNET_CRYPTO_crc16_finish(sum);
135 }
136 
137 
146 void
148  struct GNUNET_TUN_TcpHeader *tcp,
149  const void *payload,
150  uint16_t payload_length)
151 {
152  uint32_t sum;
153  uint32_t tmp;
154 
155  GNUNET_assert(20 == sizeof(struct GNUNET_TUN_TcpHeader));
156  GNUNET_assert(payload_length + sizeof(struct GNUNET_TUN_TcpHeader) ==
157  ntohs(ip->payload_length));
158  GNUNET_assert(IPPROTO_TCP == ip->next_header);
159  tcp->crc = 0;
160  sum = GNUNET_CRYPTO_crc16_step(0,
161  &ip->source_address,
162  2 * sizeof(struct in6_addr));
163  tmp = htonl(sizeof(struct GNUNET_TUN_TcpHeader) + payload_length);
164  sum = GNUNET_CRYPTO_crc16_step(sum, &tmp, sizeof(uint32_t));
165  tmp = htonl(IPPROTO_TCP);
166  sum = GNUNET_CRYPTO_crc16_step(sum, &tmp, sizeof(uint32_t));
167  sum =
168  GNUNET_CRYPTO_crc16_step(sum, tcp, sizeof(struct GNUNET_TUN_TcpHeader));
169  sum = GNUNET_CRYPTO_crc16_step(sum, payload, payload_length);
170  tcp->crc = GNUNET_CRYPTO_crc16_finish(sum);
171 }
172 
173 
182 void
184  struct GNUNET_TUN_UdpHeader *udp,
185  const void *payload,
186  uint16_t payload_length)
187 {
188  uint32_t sum;
189  uint16_t tmp;
190 
191  GNUNET_assert(8 == sizeof(struct GNUNET_TUN_UdpHeader));
192  GNUNET_assert(payload_length + sizeof(struct GNUNET_TUN_IPv4Header) +
193  sizeof(struct GNUNET_TUN_UdpHeader) ==
194  ntohs(ip->total_length));
195  GNUNET_assert(IPPROTO_UDP == ip->protocol);
196 
197  udp->crc =
198  0; /* technically optional, but we calculate it anyway, just to be sure */
199  sum = GNUNET_CRYPTO_crc16_step(0,
200  &ip->source_address,
201  sizeof(struct in_addr) * 2);
202  tmp = htons(IPPROTO_UDP);
203  sum = GNUNET_CRYPTO_crc16_step(sum, &tmp, sizeof(uint16_t));
204  tmp = htons(sizeof(struct GNUNET_TUN_UdpHeader) + payload_length);
205  sum = GNUNET_CRYPTO_crc16_step(sum, &tmp, sizeof(uint16_t));
206  sum =
207  GNUNET_CRYPTO_crc16_step(sum, udp, sizeof(struct GNUNET_TUN_UdpHeader));
208  sum = GNUNET_CRYPTO_crc16_step(sum, payload, payload_length);
209  udp->crc = GNUNET_CRYPTO_crc16_finish(sum);
210 }
211 
212 
221 void
223  struct GNUNET_TUN_UdpHeader *udp,
224  const void *payload,
225  uint16_t payload_length)
226 {
227  uint32_t sum;
228  uint32_t tmp;
229 
230  GNUNET_assert(payload_length + sizeof(struct GNUNET_TUN_UdpHeader) ==
231  ntohs(ip->payload_length));
232  GNUNET_assert(payload_length + sizeof(struct GNUNET_TUN_UdpHeader) ==
233  ntohs(udp->len));
234  GNUNET_assert(IPPROTO_UDP == ip->next_header);
235 
236  udp->crc = 0;
237  sum = GNUNET_CRYPTO_crc16_step(0,
238  &ip->source_address,
239  sizeof(struct in6_addr) * 2);
240  tmp = htons(sizeof(struct GNUNET_TUN_UdpHeader) +
241  payload_length); /* aka udp->len */
242  sum = GNUNET_CRYPTO_crc16_step(sum, &tmp, sizeof(uint32_t));
243  tmp = htons(ip->next_header);
244  sum = GNUNET_CRYPTO_crc16_step(sum, &tmp, sizeof(uint32_t));
245  sum =
246  GNUNET_CRYPTO_crc16_step(sum, udp, sizeof(struct GNUNET_TUN_UdpHeader));
247  sum = GNUNET_CRYPTO_crc16_step(sum, payload, payload_length);
248  udp->crc = GNUNET_CRYPTO_crc16_finish(sum);
249 }
250 
251 
259 void
261  const void *payload,
262  uint16_t payload_length)
263 {
264  uint32_t sum;
265 
266  GNUNET_assert(8 == sizeof(struct GNUNET_TUN_IcmpHeader));
267  icmp->crc = 0;
268  sum =
269  GNUNET_CRYPTO_crc16_step(0, icmp, sizeof(struct GNUNET_TUN_IcmpHeader));
270  sum = GNUNET_CRYPTO_crc16_step(sum, payload, payload_length);
271  icmp->crc = GNUNET_CRYPTO_crc16_finish(sum);
272 }
273 
274 
283 int
284 GNUNET_TUN_sockaddr_cmp(const struct sockaddr *sa,
285  const struct sockaddr *sb,
286  int include_port)
287 {
288  if (sa->sa_family != sb->sa_family)
289  return GNUNET_NO;
290 
291  switch (sa->sa_family)
292  {
293  case AF_INET: {
294  const struct sockaddr_in *sa4 = (const struct sockaddr_in *)sa;
295  const struct sockaddr_in *sb4 = (const struct sockaddr_in *)sb;
296  if ((include_port) && (sa4->sin_port != sb4->sin_port))
297  return GNUNET_NO;
298  return(sa4->sin_addr.s_addr == sb4->sin_addr.s_addr);
299  }
300 
301  case AF_INET6: {
302  const struct sockaddr_in6 *sa6 = (const struct sockaddr_in6 *)sa;
303  const struct sockaddr_in6 *sb6 = (const struct sockaddr_in6 *)sb;
304 
305  if ((include_port) && (sa6->sin6_port != sb6->sin6_port))
306  return GNUNET_NO;
307  return(
308  0 == memcmp(&sa6->sin6_addr, &sb6->sin6_addr, sizeof(struct in6_addr)));
309  }
310 
311  default:
312  GNUNET_break(0);
313  return GNUNET_SYSERR;
314  }
315 }
316 
317 
318 /* end of tun.c */
uint16_t identification
Unique random ID for matching up fragments.
unsigned int header_length
struct in6_addr source_address
Origin of the packet.
static int udp
Option -u: UDP requested.
Definition: gnunet-vpn.c:76
uint16_t GNUNET_CRYPTO_crc16_n(const void *buf, size_t len)
Calculate the checksum of a buffer in one step.
Definition: crypto_crc.c:160
struct in6_addr destination_address
Destination of the packet.
uint8_t ttl
How many more hops can this packet be forwarded?
struct in_addr destination_address
Destination of the packet.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
UDP packet header.
#define GNUNET_NO
Definition: gnunet_common.h:78
Standard IPv4 header.
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 IPv4 UDP checksum.
Definition: tun.c:183
uint8_t hop_limit
How many more hops can this packet be forwarded?
uint16_t len
Number of bytes of payload.
void GNUNET_TUN_calculate_tcp6_checksum(const struct GNUNET_TUN_IPv6Header *ip, struct GNUNET_TUN_TcpHeader *tcp, const void *payload, uint16_t payload_length)
Calculate IPv6 TCP checksum.
Definition: tun.c:147
void GNUNET_TUN_initialize_ipv4_header(struct GNUNET_TUN_IPv4Header *ip, uint8_t protocol, uint16_t payload_length, const struct in_addr *src, const struct in_addr *dst)
Initialize an IPv4 header.
Definition: tun.c:46
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
void GNUNET_TUN_calculate_udp6_checksum(const struct GNUNET_TUN_IPv6Header *ip, struct GNUNET_TUN_UdpHeader *udp, const void *payload, uint16_t payload_length)
Calculate IPv6 UDP checksum.
Definition: tun.c:222
uint16_t GNUNET_CRYPTO_crc16_finish(uint32_t sum)
Convert results from GNUNET_CRYPTO_crc16_step to final crc16.
Definition: crypto_crc.c:143
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 IPv4 TCP checksum.
Definition: tun.c:109
#define FRESH_TTL
IP TTL we use for packets that we assemble (8 bit unsigned integer)
Definition: tun.c:33
uint8_t next_header
For example, IPPROTO_UDP or IPPROTO_TCP.
uint32_t GNUNET_CRYPTO_crc16_step(uint32_t sum, const void *buf, size_t len)
Perform an incremental step in a CRC16 (for TCP/IP) calculation.
Definition: crypto_crc.c:124
int GNUNET_TUN_sockaddr_cmp(const struct sockaddr *sa, const struct sockaddr *sb, int include_port)
Check if two sockaddrs are equal.
Definition: tun.c:284
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
void GNUNET_TUN_calculate_icmp_checksum(struct GNUNET_TUN_IcmpHeader *icmp, const void *payload, uint16_t payload_length)
Calculate ICMP checksum.
Definition: tun.c:260
TCP packet header.
static unsigned long long payload
How much data are we currently storing in the database?
uint16_t crc
Checksum.
static int tcp
Option -t: TCP requested.
Definition: gnunet-vpn.c:71
Standard IPv6 header.
uint8_t protocol
L4-protocol, for example, IPPROTO_UDP or IPPROTO_TCP.
uint16_t payload_length
Length of the payload, excluding this header.
struct in_addr source_address
Origin of the packet.
uint16_t checksum
Checksum.
uint16_t total_length
Length of the packet, including this header.
void GNUNET_TUN_initialize_ipv6_header(struct GNUNET_TUN_IPv6Header *ip, uint8_t protocol, uint16_t payload_length, const struct in6_addr *src, const struct in6_addr *dst)
Initialize an IPv6 header.
Definition: tun.c:81
uint16_t crc
Checksum.
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).