diff options
Diffstat (limited to 'src/util/tun.c')
-rw-r--r-- | src/util/tun.c | 163 |
1 files changed, 84 insertions, 79 deletions
diff --git a/src/util/tun.c b/src/util/tun.c index 97fbaa83b..e3643d0c6 100644 --- a/src/util/tun.c +++ b/src/util/tun.c | |||
@@ -44,24 +44,27 @@ | |||
44 | */ | 44 | */ |
45 | void | 45 | void |
46 | GNUNET_TUN_initialize_ipv4_header (struct GNUNET_TUN_IPv4Header *ip, | 46 | GNUNET_TUN_initialize_ipv4_header (struct GNUNET_TUN_IPv4Header *ip, |
47 | uint8_t protocol, | 47 | uint8_t protocol, |
48 | uint16_t payload_length, | 48 | uint16_t payload_length, |
49 | const struct in_addr *src, | 49 | const struct in_addr *src, |
50 | const struct in_addr *dst) | 50 | const struct in_addr *dst) |
51 | { | 51 | { |
52 | GNUNET_assert (20 == sizeof (struct GNUNET_TUN_IPv4Header)); | 52 | GNUNET_assert (20 == sizeof (struct GNUNET_TUN_IPv4Header)); |
53 | GNUNET_assert (payload_length <= UINT16_MAX - sizeof (struct GNUNET_TUN_IPv4Header)); | 53 | GNUNET_assert (payload_length <= |
54 | UINT16_MAX - sizeof (struct GNUNET_TUN_IPv4Header)); | ||
54 | memset (ip, 0, sizeof (struct GNUNET_TUN_IPv4Header)); | 55 | memset (ip, 0, sizeof (struct GNUNET_TUN_IPv4Header)); |
55 | ip->header_length = sizeof (struct GNUNET_TUN_IPv4Header) / 4; | 56 | ip->header_length = sizeof (struct GNUNET_TUN_IPv4Header) / 4; |
56 | ip->version = 4; | 57 | ip->version = 4; |
57 | ip->total_length = htons (sizeof (struct GNUNET_TUN_IPv4Header) + payload_length); | 58 | ip->total_length = |
58 | ip->identification = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, | 59 | htons (sizeof (struct GNUNET_TUN_IPv4Header) + payload_length); |
59 | 65536); | 60 | ip->identification = |
61 | (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 65536); | ||
60 | ip->ttl = FRESH_TTL; | 62 | ip->ttl = FRESH_TTL; |
61 | ip->protocol = protocol; | 63 | ip->protocol = protocol; |
62 | ip->source_address = *src; | 64 | ip->source_address = *src; |
63 | ip->destination_address = *dst; | 65 | ip->destination_address = *dst; |
64 | ip->checksum = GNUNET_CRYPTO_crc16_n (ip, sizeof (struct GNUNET_TUN_IPv4Header)); | 66 | ip->checksum = |
67 | GNUNET_CRYPTO_crc16_n (ip, sizeof (struct GNUNET_TUN_IPv4Header)); | ||
65 | } | 68 | } |
66 | 69 | ||
67 | 70 | ||
@@ -76,13 +79,14 @@ GNUNET_TUN_initialize_ipv4_header (struct GNUNET_TUN_IPv4Header *ip, | |||
76 | */ | 79 | */ |
77 | void | 80 | void |
78 | GNUNET_TUN_initialize_ipv6_header (struct GNUNET_TUN_IPv6Header *ip, | 81 | GNUNET_TUN_initialize_ipv6_header (struct GNUNET_TUN_IPv6Header *ip, |
79 | uint8_t protocol, | 82 | uint8_t protocol, |
80 | uint16_t payload_length, | 83 | uint16_t payload_length, |
81 | const struct in6_addr *src, | 84 | const struct in6_addr *src, |
82 | const struct in6_addr *dst) | 85 | const struct in6_addr *dst) |
83 | { | 86 | { |
84 | GNUNET_assert (40 == sizeof (struct GNUNET_TUN_IPv6Header)); | 87 | GNUNET_assert (40 == sizeof (struct GNUNET_TUN_IPv6Header)); |
85 | GNUNET_assert (payload_length <= UINT16_MAX - sizeof (struct GNUNET_TUN_IPv6Header)); | 88 | GNUNET_assert (payload_length <= |
89 | UINT16_MAX - sizeof (struct GNUNET_TUN_IPv6Header)); | ||
86 | memset (ip, 0, sizeof (struct GNUNET_TUN_IPv6Header)); | 90 | memset (ip, 0, sizeof (struct GNUNET_TUN_IPv6Header)); |
87 | ip->version = 6; | 91 | ip->version = 6; |
88 | ip->next_header = protocol; | 92 | ip->next_header = protocol; |
@@ -103,27 +107,29 @@ GNUNET_TUN_initialize_ipv6_header (struct GNUNET_TUN_IPv6Header *ip, | |||
103 | */ | 107 | */ |
104 | void | 108 | void |
105 | GNUNET_TUN_calculate_tcp4_checksum (const struct GNUNET_TUN_IPv4Header *ip, | 109 | GNUNET_TUN_calculate_tcp4_checksum (const struct GNUNET_TUN_IPv4Header *ip, |
106 | struct GNUNET_TUN_TcpHeader *tcp, | 110 | struct GNUNET_TUN_TcpHeader *tcp, |
107 | const void *payload, | 111 | const void *payload, |
108 | uint16_t payload_length) | 112 | uint16_t payload_length) |
109 | { | 113 | { |
110 | uint32_t sum; | 114 | uint32_t sum; |
111 | uint16_t tmp; | 115 | uint16_t tmp; |
112 | 116 | ||
113 | GNUNET_assert (20 == sizeof (struct GNUNET_TUN_TcpHeader)); | 117 | GNUNET_assert (20 == sizeof (struct GNUNET_TUN_TcpHeader)); |
114 | GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_IPv4Header) + sizeof (struct GNUNET_TUN_TcpHeader) == | 118 | GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_IPv4Header) + |
115 | ntohs (ip->total_length)); | 119 | sizeof (struct GNUNET_TUN_TcpHeader) == |
120 | ntohs (ip->total_length)); | ||
116 | GNUNET_assert (IPPROTO_TCP == ip->protocol); | 121 | GNUNET_assert (IPPROTO_TCP == ip->protocol); |
117 | 122 | ||
118 | tcp->crc = 0; | 123 | tcp->crc = 0; |
119 | sum = GNUNET_CRYPTO_crc16_step (0, | 124 | sum = GNUNET_CRYPTO_crc16_step (0, |
120 | &ip->source_address, | 125 | &ip->source_address, |
121 | sizeof (struct in_addr) * 2); | 126 | sizeof (struct in_addr) * 2); |
122 | tmp = htons (IPPROTO_TCP); | 127 | tmp = htons (IPPROTO_TCP); |
123 | sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint16_t)); | 128 | sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint16_t)); |
124 | tmp = htons (payload_length + sizeof (struct GNUNET_TUN_TcpHeader)); | 129 | tmp = htons (payload_length + sizeof (struct GNUNET_TUN_TcpHeader)); |
125 | sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint16_t)); | 130 | sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint16_t)); |
126 | sum = GNUNET_CRYPTO_crc16_step (sum, tcp, sizeof (struct GNUNET_TUN_TcpHeader)); | 131 | sum = |
132 | GNUNET_CRYPTO_crc16_step (sum, tcp, sizeof (struct GNUNET_TUN_TcpHeader)); | ||
127 | sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length); | 133 | sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length); |
128 | tcp->crc = GNUNET_CRYPTO_crc16_finish (sum); | 134 | tcp->crc = GNUNET_CRYPTO_crc16_finish (sum); |
129 | } | 135 | } |
@@ -139,25 +145,27 @@ GNUNET_TUN_calculate_tcp4_checksum (const struct GNUNET_TUN_IPv4Header *ip, | |||
139 | */ | 145 | */ |
140 | void | 146 | void |
141 | GNUNET_TUN_calculate_tcp6_checksum (const struct GNUNET_TUN_IPv6Header *ip, | 147 | GNUNET_TUN_calculate_tcp6_checksum (const struct GNUNET_TUN_IPv6Header *ip, |
142 | struct GNUNET_TUN_TcpHeader *tcp, | 148 | struct GNUNET_TUN_TcpHeader *tcp, |
143 | const void *payload, | 149 | const void *payload, |
144 | uint16_t payload_length) | 150 | uint16_t payload_length) |
145 | { | 151 | { |
146 | uint32_t sum; | 152 | uint32_t sum; |
147 | uint32_t tmp; | 153 | uint32_t tmp; |
148 | 154 | ||
149 | GNUNET_assert (20 == sizeof (struct GNUNET_TUN_TcpHeader)); | 155 | GNUNET_assert (20 == sizeof (struct GNUNET_TUN_TcpHeader)); |
150 | GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_TcpHeader) == | 156 | GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_TcpHeader) == |
151 | ntohs (ip->payload_length)); | 157 | ntohs (ip->payload_length)); |
152 | GNUNET_assert (IPPROTO_TCP == ip->next_header); | 158 | GNUNET_assert (IPPROTO_TCP == ip->next_header); |
153 | tcp->crc = 0; | 159 | tcp->crc = 0; |
154 | sum = GNUNET_CRYPTO_crc16_step (0, &ip->source_address, 2 * sizeof (struct in6_addr)); | 160 | sum = GNUNET_CRYPTO_crc16_step (0, |
161 | &ip->source_address, | ||
162 | 2 * sizeof (struct in6_addr)); | ||
155 | tmp = htonl (sizeof (struct GNUNET_TUN_TcpHeader) + payload_length); | 163 | tmp = htonl (sizeof (struct GNUNET_TUN_TcpHeader) + payload_length); |
156 | sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t)); | 164 | sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t)); |
157 | tmp = htonl (IPPROTO_TCP); | 165 | tmp = htonl (IPPROTO_TCP); |
158 | sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t)); | 166 | sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t)); |
159 | sum = GNUNET_CRYPTO_crc16_step (sum, tcp, | 167 | sum = |
160 | sizeof (struct GNUNET_TUN_TcpHeader)); | 168 | GNUNET_CRYPTO_crc16_step (sum, tcp, sizeof (struct GNUNET_TUN_TcpHeader)); |
161 | sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length); | 169 | sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length); |
162 | tcp->crc = GNUNET_CRYPTO_crc16_finish (sum); | 170 | tcp->crc = GNUNET_CRYPTO_crc16_finish (sum); |
163 | } | 171 | } |
@@ -173,36 +181,31 @@ GNUNET_TUN_calculate_tcp6_checksum (const struct GNUNET_TUN_IPv6Header *ip, | |||
173 | */ | 181 | */ |
174 | void | 182 | void |
175 | GNUNET_TUN_calculate_udp4_checksum (const struct GNUNET_TUN_IPv4Header *ip, | 183 | GNUNET_TUN_calculate_udp4_checksum (const struct GNUNET_TUN_IPv4Header *ip, |
176 | struct GNUNET_TUN_UdpHeader *udp, | 184 | struct GNUNET_TUN_UdpHeader *udp, |
177 | const void *payload, | 185 | const void *payload, |
178 | uint16_t payload_length) | 186 | uint16_t payload_length) |
179 | { | 187 | { |
180 | uint32_t sum; | 188 | uint32_t sum; |
181 | uint16_t tmp; | 189 | uint16_t tmp; |
182 | 190 | ||
183 | GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader)); | 191 | GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader)); |
184 | GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_IPv4Header) + sizeof (struct GNUNET_TUN_UdpHeader) == | 192 | GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_IPv4Header) + |
185 | ntohs (ip->total_length)); | 193 | sizeof (struct GNUNET_TUN_UdpHeader) == |
194 | ntohs (ip->total_length)); | ||
186 | GNUNET_assert (IPPROTO_UDP == ip->protocol); | 195 | GNUNET_assert (IPPROTO_UDP == ip->protocol); |
187 | 196 | ||
188 | udp->crc = 0; /* technically optional, but we calculate it anyway, just to be sure */ | 197 | udp->crc = |
198 | 0; /* technically optional, but we calculate it anyway, just to be sure */ | ||
189 | sum = GNUNET_CRYPTO_crc16_step (0, | 199 | sum = GNUNET_CRYPTO_crc16_step (0, |
190 | &ip->source_address, | 200 | &ip->source_address, |
191 | sizeof (struct in_addr) * 2); | 201 | sizeof (struct in_addr) * 2); |
192 | tmp = htons (IPPROTO_UDP); | 202 | tmp = htons (IPPROTO_UDP); |
193 | sum = GNUNET_CRYPTO_crc16_step (sum, | 203 | sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint16_t)); |
194 | &tmp, | ||
195 | sizeof (uint16_t)); | ||
196 | tmp = htons (sizeof (struct GNUNET_TUN_UdpHeader) + payload_length); | 204 | tmp = htons (sizeof (struct GNUNET_TUN_UdpHeader) + payload_length); |
197 | sum = GNUNET_CRYPTO_crc16_step (sum, | 205 | sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint16_t)); |
198 | &tmp, | 206 | sum = |
199 | sizeof (uint16_t)); | 207 | GNUNET_CRYPTO_crc16_step (sum, udp, sizeof (struct GNUNET_TUN_UdpHeader)); |
200 | sum = GNUNET_CRYPTO_crc16_step (sum, | 208 | sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length); |
201 | udp, | ||
202 | sizeof (struct GNUNET_TUN_UdpHeader)); | ||
203 | sum = GNUNET_CRYPTO_crc16_step (sum, | ||
204 | payload, | ||
205 | payload_length); | ||
206 | udp->crc = GNUNET_CRYPTO_crc16_finish (sum); | 209 | udp->crc = GNUNET_CRYPTO_crc16_finish (sum); |
207 | } | 210 | } |
208 | 211 | ||
@@ -217,28 +220,30 @@ GNUNET_TUN_calculate_udp4_checksum (const struct GNUNET_TUN_IPv4Header *ip, | |||
217 | */ | 220 | */ |
218 | void | 221 | void |
219 | GNUNET_TUN_calculate_udp6_checksum (const struct GNUNET_TUN_IPv6Header *ip, | 222 | GNUNET_TUN_calculate_udp6_checksum (const struct GNUNET_TUN_IPv6Header *ip, |
220 | struct GNUNET_TUN_UdpHeader *udp, | 223 | struct GNUNET_TUN_UdpHeader *udp, |
221 | const void *payload, | 224 | const void *payload, |
222 | uint16_t payload_length) | 225 | uint16_t payload_length) |
223 | { | 226 | { |
224 | uint32_t sum; | 227 | uint32_t sum; |
225 | uint32_t tmp; | 228 | uint32_t tmp; |
226 | 229 | ||
227 | GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_UdpHeader) == | 230 | GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_UdpHeader) == |
228 | ntohs (ip->payload_length)); | 231 | ntohs (ip->payload_length)); |
229 | GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_UdpHeader) == | 232 | GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_UdpHeader) == |
230 | ntohs (udp->len)); | 233 | ntohs (udp->len)); |
231 | GNUNET_assert (IPPROTO_UDP == ip->next_header); | 234 | GNUNET_assert (IPPROTO_UDP == ip->next_header); |
232 | 235 | ||
233 | udp->crc = 0; | 236 | udp->crc = 0; |
234 | sum = GNUNET_CRYPTO_crc16_step (0, | 237 | sum = GNUNET_CRYPTO_crc16_step (0, |
235 | &ip->source_address, | 238 | &ip->source_address, |
236 | sizeof (struct in6_addr) * 2); | 239 | sizeof (struct in6_addr) * 2); |
237 | tmp = htons (sizeof (struct GNUNET_TUN_UdpHeader) + payload_length); /* aka udp->len */ | 240 | tmp = htons (sizeof (struct GNUNET_TUN_UdpHeader) + |
241 | payload_length); /* aka udp->len */ | ||
238 | sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t)); | 242 | sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t)); |
239 | tmp = htons (ip->next_header); | 243 | tmp = htons (ip->next_header); |
240 | sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t)); | 244 | sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t)); |
241 | sum = GNUNET_CRYPTO_crc16_step (sum, udp, sizeof (struct GNUNET_TUN_UdpHeader)); | 245 | sum = |
246 | GNUNET_CRYPTO_crc16_step (sum, udp, sizeof (struct GNUNET_TUN_UdpHeader)); | ||
242 | sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length); | 247 | sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length); |
243 | udp->crc = GNUNET_CRYPTO_crc16_finish (sum); | 248 | udp->crc = GNUNET_CRYPTO_crc16_finish (sum); |
244 | } | 249 | } |
@@ -253,16 +258,15 @@ GNUNET_TUN_calculate_udp6_checksum (const struct GNUNET_TUN_IPv6Header *ip, | |||
253 | */ | 258 | */ |
254 | void | 259 | void |
255 | GNUNET_TUN_calculate_icmp_checksum (struct GNUNET_TUN_IcmpHeader *icmp, | 260 | GNUNET_TUN_calculate_icmp_checksum (struct GNUNET_TUN_IcmpHeader *icmp, |
256 | const void *payload, | 261 | const void *payload, |
257 | uint16_t payload_length) | 262 | uint16_t payload_length) |
258 | { | 263 | { |
259 | uint32_t sum; | 264 | uint32_t sum; |
260 | 265 | ||
261 | GNUNET_assert (8 == sizeof (struct GNUNET_TUN_IcmpHeader)); | 266 | GNUNET_assert (8 == sizeof (struct GNUNET_TUN_IcmpHeader)); |
262 | icmp->crc = 0; | 267 | icmp->crc = 0; |
263 | sum = GNUNET_CRYPTO_crc16_step (0, | 268 | sum = |
264 | icmp, | 269 | GNUNET_CRYPTO_crc16_step (0, icmp, sizeof (struct GNUNET_TUN_IcmpHeader)); |
265 | sizeof (struct GNUNET_TUN_IcmpHeader)); | ||
266 | sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length); | 270 | sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length); |
267 | icmp->crc = GNUNET_CRYPTO_crc16_finish (sum); | 271 | icmp->crc = GNUNET_CRYPTO_crc16_finish (sum); |
268 | } | 272 | } |
@@ -286,21 +290,22 @@ GNUNET_TUN_sockaddr_cmp (const struct sockaddr *sa, | |||
286 | 290 | ||
287 | switch (sa->sa_family) | 291 | switch (sa->sa_family) |
288 | { | 292 | { |
289 | case AF_INET: | 293 | case AF_INET: { |
290 | { | 294 | const struct sockaddr_in *sa4 = (const struct sockaddr_in *) sa; |
291 | const struct sockaddr_in *sa4 = (const struct sockaddr_in *) sa; | 295 | const struct sockaddr_in *sb4 = (const struct sockaddr_in *) sb; |
292 | const struct sockaddr_in *sb4 = (const struct sockaddr_in *) sb; | 296 | if ((include_port) && (sa4->sin_port != sb4->sin_port)) |
293 | return (sa4->sin_addr.s_addr == sb4->sin_addr.s_addr); | 297 | return GNUNET_NO; |
294 | } | 298 | return (sa4->sin_addr.s_addr == sb4->sin_addr.s_addr); |
295 | case AF_INET6: | 299 | } |
296 | { | 300 | case AF_INET6: { |
297 | const struct sockaddr_in6 *sa6 = (const struct sockaddr_in6 *) sa; | 301 | const struct sockaddr_in6 *sa6 = (const struct sockaddr_in6 *) sa; |
298 | const struct sockaddr_in6 *sb6 = (const struct sockaddr_in6 *) sb; | 302 | const struct sockaddr_in6 *sb6 = (const struct sockaddr_in6 *) sb; |
299 | 303 | ||
300 | return (0 == memcmp(&sa6->sin6_addr, | 304 | if ((include_port) && (sa6->sin6_port != sb6->sin6_port)) |
301 | &sb6->sin6_addr, | 305 | return GNUNET_NO; |
302 | sizeof (struct in6_addr))); | 306 | return ( |
303 | } | 307 | 0 == memcmp (&sa6->sin6_addr, &sb6->sin6_addr, sizeof (struct in6_addr))); |
308 | } | ||
304 | default: | 309 | default: |
305 | GNUNET_break (0); | 310 | GNUNET_break (0); |
306 | return GNUNET_SYSERR; | 311 | return GNUNET_SYSERR; |