aboutsummaryrefslogtreecommitdiff
path: root/src/lib/util/tun.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/util/tun.c')
-rw-r--r--src/lib/util/tun.c281
1 files changed, 281 insertions, 0 deletions
diff --git a/src/lib/util/tun.c b/src/lib/util/tun.c
new file mode 100644
index 000000000..c4ac6ff88
--- /dev/null
+++ b/src/lib/util/tun.c
@@ -0,0 +1,281 @@
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
21/**
22 * @file tun/tun.c
23 * @brief standard IP calculations for TUN interaction
24 * @author Philipp Toelke
25 * @author Christian Grothoff
26 */
27
28#include "platform.h"
29#include "gnunet_util_lib.h"
30
31/**
32 * IP TTL we use for packets that we assemble (8 bit unsigned integer)
33 */
34#define FRESH_TTL 64
35
36
37/**
38 * Initialize an IPv4 header.
39 *
40 * @param ip header to initialize
41 * @param protocol protocol to use (e.g. IPPROTO_UDP)
42 * @param payload_length number of bytes of payload that follow (excluding IPv4 header)
43 * @param src source IP address to use
44 * @param dst destination IP address to use
45 */
46void
47GNUNET_TUN_initialize_ipv4_header (struct GNUNET_TUN_IPv4Header *ip,
48 uint8_t protocol,
49 uint16_t payload_length,
50 const struct in_addr *src,
51 const struct in_addr *dst)
52{
53 GNUNET_assert (20 == sizeof(struct GNUNET_TUN_IPv4Header));
54 GNUNET_assert (payload_length <=
55 UINT16_MAX - sizeof(struct GNUNET_TUN_IPv4Header));
56 memset (ip, 0, sizeof(struct GNUNET_TUN_IPv4Header));
57 ip->header_length = sizeof(struct GNUNET_TUN_IPv4Header) / 4;
58 ip->version = 4;
59 ip->total_length =
60 htons (sizeof(struct GNUNET_TUN_IPv4Header) + payload_length);
61 ip->identification =
62 (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 65536);
63 ip->ttl = FRESH_TTL;
64 ip->protocol = protocol;
65 ip->source_address = *src;
66 ip->destination_address = *dst;
67 ip->checksum =
68 GNUNET_CRYPTO_crc16_n (ip, sizeof(struct GNUNET_TUN_IPv4Header));
69}
70
71
72/**
73 * Initialize an IPv6 header.
74 *
75 * @param ip header to initialize
76 * @param protocol protocol to use (e.g. IPPROTO_UDP), technically "next_header" for IPv6
77 * @param payload_length number of bytes of payload that follow (excluding IPv6 header)
78 * @param src source IP address to use
79 * @param dst destination IP address to use
80 */
81void
82GNUNET_TUN_initialize_ipv6_header (struct GNUNET_TUN_IPv6Header *ip,
83 uint8_t protocol,
84 uint16_t payload_length,
85 const struct in6_addr *src,
86 const struct in6_addr *dst)
87{
88 GNUNET_assert (40 == sizeof(struct GNUNET_TUN_IPv6Header));
89 GNUNET_assert (payload_length <=
90 UINT16_MAX - sizeof(struct GNUNET_TUN_IPv6Header));
91 memset (ip, 0, sizeof(struct GNUNET_TUN_IPv6Header));
92 ip->version = 6;
93 ip->next_header = protocol;
94 ip->payload_length = htons ((uint16_t) payload_length);
95 ip->hop_limit = FRESH_TTL;
96 ip->destination_address = *dst;
97 ip->source_address = *src;
98}
99
100
101void
102GNUNET_TUN_calculate_tcp4_checksum (const struct GNUNET_TUN_IPv4Header *ip,
103 struct GNUNET_TUN_TcpHeader *tcp,
104 const void *payload,
105 uint16_t payload_length)
106{
107 uint32_t sum;
108 uint16_t tmp;
109
110 GNUNET_assert (20 == sizeof(struct GNUNET_TUN_TcpHeader));
111 GNUNET_assert (payload_length + sizeof(struct GNUNET_TUN_IPv4Header)
112 + sizeof(struct GNUNET_TUN_TcpHeader) ==
113 ntohs (ip->total_length));
114 GNUNET_assert (IPPROTO_TCP == ip->protocol);
115
116 tcp->crc = 0;
117 sum = GNUNET_CRYPTO_crc16_step (0,
118 &ip->source_address,
119 sizeof(struct in_addr) * 2);
120 tmp = htons (IPPROTO_TCP);
121 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof(uint16_t));
122 tmp = htons (payload_length + sizeof(struct GNUNET_TUN_TcpHeader));
123 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof(uint16_t));
124 sum =
125 GNUNET_CRYPTO_crc16_step (sum, tcp, sizeof(struct GNUNET_TUN_TcpHeader));
126 sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length);
127 tcp->crc = GNUNET_CRYPTO_crc16_finish (sum);
128}
129
130
131void
132GNUNET_TUN_calculate_tcp6_checksum (const struct GNUNET_TUN_IPv6Header *ip,
133 struct GNUNET_TUN_TcpHeader *tcp,
134 const void *payload,
135 uint16_t payload_length)
136{
137 uint32_t sum;
138 uint32_t tmp;
139
140 GNUNET_assert (20 == sizeof(struct GNUNET_TUN_TcpHeader));
141 GNUNET_assert (payload_length + sizeof(struct GNUNET_TUN_TcpHeader) ==
142 ntohs (ip->payload_length));
143 GNUNET_assert (IPPROTO_TCP == ip->next_header);
144 tcp->crc = 0;
145 sum = GNUNET_CRYPTO_crc16_step (0,
146 &ip->source_address,
147 2 * sizeof(struct in6_addr));
148 tmp = htonl (sizeof(struct GNUNET_TUN_TcpHeader) + payload_length);
149 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof(uint32_t));
150 tmp = htonl (IPPROTO_TCP);
151 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof(uint32_t));
152 sum =
153 GNUNET_CRYPTO_crc16_step (sum, tcp, sizeof(struct GNUNET_TUN_TcpHeader));
154 sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length);
155 tcp->crc = GNUNET_CRYPTO_crc16_finish (sum);
156}
157
158
159void
160GNUNET_TUN_calculate_udp4_checksum (const struct GNUNET_TUN_IPv4Header *ip,
161 struct GNUNET_TUN_UdpHeader *udp,
162 const void *payload,
163 uint16_t payload_length)
164{
165 uint32_t sum;
166 uint16_t tmp;
167
168 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
169 GNUNET_assert (payload_length + sizeof(struct GNUNET_TUN_IPv4Header)
170 + sizeof(struct GNUNET_TUN_UdpHeader) ==
171 ntohs (ip->total_length));
172 GNUNET_assert (IPPROTO_UDP == ip->protocol);
173
174 udp->crc =
175 0; /* technically optional, but we calculate it anyway, just to be sure */
176 sum = GNUNET_CRYPTO_crc16_step (0,
177 &ip->source_address,
178 sizeof(struct in_addr) * 2);
179 tmp = htons (IPPROTO_UDP);
180 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof(uint16_t));
181 tmp = htons (sizeof(struct GNUNET_TUN_UdpHeader) + payload_length);
182 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof(uint16_t));
183 sum =
184 GNUNET_CRYPTO_crc16_step (sum, udp, sizeof(struct GNUNET_TUN_UdpHeader));
185 sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length);
186 udp->crc = GNUNET_CRYPTO_crc16_finish (sum);
187}
188
189
190void
191GNUNET_TUN_calculate_udp6_checksum (const struct GNUNET_TUN_IPv6Header *ip,
192 struct GNUNET_TUN_UdpHeader *udp,
193 const void *payload,
194 uint16_t payload_length)
195{
196 uint32_t sum;
197 uint32_t tmp;
198
199 GNUNET_assert (payload_length + sizeof(struct GNUNET_TUN_UdpHeader) ==
200 ntohs (ip->payload_length));
201 GNUNET_assert (payload_length + sizeof(struct GNUNET_TUN_UdpHeader) ==
202 ntohs (udp->len));
203 GNUNET_assert (IPPROTO_UDP == ip->next_header);
204
205 udp->crc = 0;
206 sum = GNUNET_CRYPTO_crc16_step (0,
207 &ip->source_address,
208 sizeof(struct in6_addr) * 2);
209 tmp = htons (sizeof(struct GNUNET_TUN_UdpHeader)
210 + payload_length); /* aka udp->len */
211 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof(uint32_t));
212 tmp = htons (ip->next_header);
213 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof(uint32_t));
214 sum =
215 GNUNET_CRYPTO_crc16_step (sum, udp, sizeof(struct GNUNET_TUN_UdpHeader));
216 sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length);
217 udp->crc = GNUNET_CRYPTO_crc16_finish (sum);
218}
219
220
221void
222GNUNET_TUN_calculate_icmp_checksum (struct GNUNET_TUN_IcmpHeader *icmp,
223 const void *payload,
224 uint16_t payload_length)
225{
226 uint32_t sum;
227
228 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_IcmpHeader));
229 icmp->crc = 0;
230 sum =
231 GNUNET_CRYPTO_crc16_step (0, icmp, sizeof(struct GNUNET_TUN_IcmpHeader));
232 sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length);
233 icmp->crc = GNUNET_CRYPTO_crc16_finish (sum);
234}
235
236
237/**
238 * Check if two sockaddrs are equal.
239 *
240 * @param sa one address
241 * @param sb another address
242 * @param include_port also check ports
243 * @return #GNUNET_YES if they are equal
244 */
245int
246GNUNET_TUN_sockaddr_cmp (const struct sockaddr *sa,
247 const struct sockaddr *sb,
248 int include_port)
249{
250 if (sa->sa_family != sb->sa_family)
251 return GNUNET_NO;
252
253 switch (sa->sa_family)
254 {
255 case AF_INET: {
256 const struct sockaddr_in *sa4 = (const struct sockaddr_in *) sa;
257 const struct sockaddr_in *sb4 = (const struct sockaddr_in *) sb;
258 if ((include_port) && (sa4->sin_port != sb4->sin_port))
259 return GNUNET_NO;
260 return(sa4->sin_addr.s_addr == sb4->sin_addr.s_addr);
261 }
262
263 case AF_INET6: {
264 const struct sockaddr_in6 *sa6 = (const struct sockaddr_in6 *) sa;
265 const struct sockaddr_in6 *sb6 = (const struct sockaddr_in6 *) sb;
266
267 if ((include_port) && (sa6->sin6_port != sb6->sin6_port))
268 return GNUNET_NO;
269 return(
270 0 == memcmp (&sa6->sin6_addr, &sb6->sin6_addr, sizeof(struct
271 in6_addr)));
272 }
273
274 default:
275 GNUNET_break (0);
276 return GNUNET_SYSERR;
277 }
278}
279
280
281/* end of tun.c */