diff options
author | Christian Grothoff <christian@grothoff.org> | 2010-08-22 13:36:33 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2010-08-22 13:36:33 +0000 |
commit | b4e21c6afcb6cd772c66b2c0ae3199f193c972c7 (patch) | |
tree | 10cf25bb37ee491ac5d083d93678944e0e510f1c /src/transport/gnunet-nat-client.c | |
parent | 1355ed0acd88356beccc25dfc710ef0d458b5b96 (diff) | |
download | gnunet-b4e21c6afcb6cd772c66b2c0ae3199f193c972c7.tar.gz gnunet-b4e21c6afcb6cd772c66b2c0ae3199f193c972c7.zip |
audit
Diffstat (limited to 'src/transport/gnunet-nat-client.c')
-rw-r--r-- | src/transport/gnunet-nat-client.c | 101 |
1 files changed, 51 insertions, 50 deletions
diff --git a/src/transport/gnunet-nat-client.c b/src/transport/gnunet-nat-client.c index bff86cc93..3e35aa8f4 100644 --- a/src/transport/gnunet-nat-client.c +++ b/src/transport/gnunet-nat-client.c | |||
@@ -21,7 +21,7 @@ | |||
21 | /** | 21 | /** |
22 | * @file src/transport/gnunet-nat-client.c | 22 | * @file src/transport/gnunet-nat-client.c |
23 | * @brief Tool to help bypass NATs using ICMP method; must run as root (SUID will do) | 23 | * @brief Tool to help bypass NATs using ICMP method; must run as root (SUID will do) |
24 | * This code will work under GNU/Linux only. | 24 | * This code will work under GNU/Linux only. |
25 | * @author Christian Grothoff | 25 | * @author Christian Grothoff |
26 | * | 26 | * |
27 | * This program will send ONE ICMP message using RAW sockets | 27 | * This program will send ONE ICMP message using RAW sockets |
@@ -39,6 +39,7 @@ | |||
39 | * | 39 | * |
40 | * - Christian Grothoff | 40 | * - Christian Grothoff |
41 | * - Nathan Evans | 41 | * - Nathan Evans |
42 | * - Benjamin Kuperman (22 Aug 2010) | ||
42 | */ | 43 | */ |
43 | #if HAVE_CONFIG_H | 44 | #if HAVE_CONFIG_H |
44 | /* Just needed for HAVE_SOCKADDR_IN_SIN_LEN test macro! */ | 45 | /* Just needed for HAVE_SOCKADDR_IN_SIN_LEN test macro! */ |
@@ -46,7 +47,7 @@ | |||
46 | #else | 47 | #else |
47 | #define _GNU_SOURCE | 48 | #define _GNU_SOURCE |
48 | #endif | 49 | #endif |
49 | #include <sys/types.h> | 50 | #include <sys/types.h> |
50 | #include <sys/socket.h> | 51 | #include <sys/socket.h> |
51 | #include <arpa/inet.h> | 52 | #include <arpa/inet.h> |
52 | #include <sys/types.h> | 53 | #include <sys/types.h> |
@@ -58,7 +59,7 @@ | |||
58 | #include <stdint.h> | 59 | #include <stdint.h> |
59 | #include <netinet/ip.h> | 60 | #include <netinet/ip.h> |
60 | #include <netinet/ip_icmp.h> | 61 | #include <netinet/ip_icmp.h> |
61 | #include <netinet/in.h> | 62 | #include <netinet/in.h> |
62 | 63 | ||
63 | /** | 64 | /** |
64 | * Must match IP given in the server. | 65 | * Must match IP given in the server. |
@@ -70,11 +71,11 @@ | |||
70 | /** | 71 | /** |
71 | * IPv4 header. | 72 | * IPv4 header. |
72 | */ | 73 | */ |
73 | struct ip_header | 74 | struct ip_header |
74 | { | 75 | { |
75 | 76 | ||
76 | /** | 77 | /** |
77 | * Version (4 bits) + Internet header length (4 bits) | 78 | * Version (4 bits) + Internet header length (4 bits) |
78 | */ | 79 | */ |
79 | uint8_t vers_ihl; | 80 | uint8_t vers_ihl; |
80 | 81 | ||
@@ -104,10 +105,10 @@ struct ip_header | |||
104 | uint8_t ttl; | 105 | uint8_t ttl; |
105 | 106 | ||
106 | /** | 107 | /** |
107 | * Protocol | 108 | * Protocol |
108 | */ | 109 | */ |
109 | uint8_t proto; | 110 | uint8_t proto; |
110 | 111 | ||
111 | /** | 112 | /** |
112 | * Header checksum | 113 | * Header checksum |
113 | */ | 114 | */ |
@@ -119,7 +120,7 @@ struct ip_header | |||
119 | uint32_t src_ip; | 120 | uint32_t src_ip; |
120 | 121 | ||
121 | /** | 122 | /** |
122 | * Destination address | 123 | * Destination address |
123 | */ | 124 | */ |
124 | uint32_t dst_ip; | 125 | uint32_t dst_ip; |
125 | }; | 126 | }; |
@@ -127,7 +128,7 @@ struct ip_header | |||
127 | /** | 128 | /** |
128 | * Format of ICMP packet. | 129 | * Format of ICMP packet. |
129 | */ | 130 | */ |
130 | struct icmp_ttl_exceeded_header | 131 | struct icmp_ttl_exceeded_header |
131 | { | 132 | { |
132 | uint8_t type; | 133 | uint8_t type; |
133 | 134 | ||
@@ -161,7 +162,7 @@ struct udp_header | |||
161 | uint16_t dst_port; | 162 | uint16_t dst_port; |
162 | 163 | ||
163 | uint16_t length; | 164 | uint16_t length; |
164 | 165 | ||
165 | uint16_t crc; | 166 | uint16_t crc; |
166 | }; | 167 | }; |
167 | 168 | ||
@@ -174,7 +175,7 @@ static int rawsock; | |||
174 | * Target "dummy" address of the packet we pretend to respond to. | 175 | * Target "dummy" address of the packet we pretend to respond to. |
175 | */ | 176 | */ |
176 | static struct in_addr dummy; | 177 | static struct in_addr dummy; |
177 | 178 | ||
178 | /** | 179 | /** |
179 | * Our "source" port. | 180 | * Our "source" port. |
180 | */ | 181 | */ |
@@ -188,16 +189,16 @@ static uint16_t port; | |||
188 | * @param bytes number of bytes in data (must be multiple of 2) | 189 | * @param bytes number of bytes in data (must be multiple of 2) |
189 | * @return the CRC 16. | 190 | * @return the CRC 16. |
190 | */ | 191 | */ |
191 | static uint16_t | 192 | static uint16_t |
192 | calc_checksum (const uint16_t *data, | 193 | calc_checksum (const uint16_t *data, |
193 | unsigned int bytes) | 194 | unsigned int bytes) |
194 | { | 195 | { |
195 | uint32_t sum; | 196 | uint32_t sum; |
196 | unsigned int i; | 197 | unsigned int i; |
197 | 198 | ||
198 | sum = 0; | 199 | sum = 0; |
199 | for (i=0;i<bytes/2;i++) | 200 | for (i=0;i<bytes/2;i++) |
200 | sum += data[i]; | 201 | sum += data[i]; |
201 | sum = (sum & 0xffff) + (sum >> 16); | 202 | sum = (sum & 0xffff) + (sum >> 16); |
202 | sum = htons(0xffff - sum); | 203 | sum = htons(0xffff - sum); |
203 | return sum; | 204 | return sum; |
@@ -214,8 +215,8 @@ static void | |||
214 | send_icmp_udp (const struct in_addr *my_ip, | 215 | send_icmp_udp (const struct in_addr *my_ip, |
215 | const struct in_addr *other) | 216 | const struct in_addr *other) |
216 | { | 217 | { |
217 | char packet[sizeof(struct ip_header) * 2 + | 218 | char packet[sizeof(struct ip_header) * 2 + |
218 | sizeof(struct icmp_ttl_exceeded_header) + | 219 | sizeof(struct icmp_ttl_exceeded_header) + |
219 | sizeof(struct udp_header)]; | 220 | sizeof(struct udp_header)]; |
220 | struct ip_header ip_pkt; | 221 | struct ip_header ip_pkt; |
221 | struct icmp_ttl_exceeded_header icmp_pkt; | 222 | struct icmp_ttl_exceeded_header icmp_pkt; |
@@ -236,10 +237,10 @@ send_icmp_udp (const struct in_addr *my_ip, | |||
236 | ip_pkt.checksum = 0; | 237 | ip_pkt.checksum = 0; |
237 | ip_pkt.src_ip = my_ip->s_addr; | 238 | ip_pkt.src_ip = my_ip->s_addr; |
238 | ip_pkt.dst_ip = other->s_addr; | 239 | ip_pkt.dst_ip = other->s_addr; |
239 | ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, | 240 | ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, |
240 | sizeof (struct ip_header))); | 241 | sizeof (struct ip_header))); |
241 | memcpy(&packet[off], | 242 | memcpy(&packet[off], |
242 | &ip_pkt, | 243 | &ip_pkt, |
243 | sizeof(struct ip_header)); | 244 | sizeof(struct ip_header)); |
244 | off += sizeof(struct ip_header); | 245 | off += sizeof(struct ip_header); |
245 | 246 | ||
@@ -248,7 +249,7 @@ send_icmp_udp (const struct in_addr *my_ip, | |||
248 | icmp_pkt.checksum = 0; | 249 | icmp_pkt.checksum = 0; |
249 | icmp_pkt.unused = 0; | 250 | icmp_pkt.unused = 0; |
250 | memcpy(&packet[off], | 251 | memcpy(&packet[off], |
251 | &icmp_pkt, | 252 | &icmp_pkt, |
252 | sizeof(struct icmp_ttl_exceeded_header)); | 253 | sizeof(struct icmp_ttl_exceeded_header)); |
253 | off += sizeof(struct icmp_ttl_exceeded_header); | 254 | off += sizeof(struct icmp_ttl_exceeded_header); |
254 | 255 | ||
@@ -266,8 +267,8 @@ send_icmp_udp (const struct in_addr *my_ip, | |||
266 | ip_pkt.dst_ip = dummy.s_addr; | 267 | ip_pkt.dst_ip = dummy.s_addr; |
267 | ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, | 268 | ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, |
268 | sizeof (struct ip_header))); | 269 | sizeof (struct ip_header))); |
269 | memcpy(&packet[off], | 270 | memcpy(&packet[off], |
270 | &ip_pkt, | 271 | &ip_pkt, |
271 | sizeof(struct ip_header)); | 272 | sizeof(struct ip_header)); |
272 | off += sizeof(struct ip_header); | 273 | off += sizeof(struct ip_header); |
273 | 274 | ||
@@ -276,7 +277,7 @@ send_icmp_udp (const struct in_addr *my_ip, | |||
276 | udp_pkt.dst_port = htons(NAT_TRAV_PORT); | 277 | udp_pkt.dst_port = htons(NAT_TRAV_PORT); |
277 | udp_pkt.length = htons (port); | 278 | udp_pkt.length = htons (port); |
278 | udp_pkt.crc = 0; | 279 | udp_pkt.crc = 0; |
279 | memcpy(&packet[off], | 280 | memcpy(&packet[off], |
280 | &udp_pkt, | 281 | &udp_pkt, |
281 | sizeof(struct udp_header)); | 282 | sizeof(struct udp_header)); |
282 | off += sizeof(struct udp_header); | 283 | off += sizeof(struct udp_header); |
@@ -286,9 +287,9 @@ send_icmp_udp (const struct in_addr *my_ip, | |||
286 | sizeof (struct icmp_ttl_exceeded_header) + | 287 | sizeof (struct icmp_ttl_exceeded_header) + |
287 | sizeof (struct ip_header) + | 288 | sizeof (struct ip_header) + |
288 | sizeof (struct udp_header))); | 289 | sizeof (struct udp_header))); |
289 | memcpy (&packet[sizeof(struct ip_header)], | 290 | memcpy (&packet[sizeof(struct ip_header)], |
290 | &icmp_pkt, | 291 | &icmp_pkt, |
291 | sizeof (struct icmp_ttl_exceeded_header)); | 292 | sizeof (struct icmp_ttl_exceeded_header)); |
292 | 293 | ||
293 | memset (&dst, 0, sizeof (dst)); | 294 | memset (&dst, 0, sizeof (dst)); |
294 | dst.sin_family = AF_INET; | 295 | dst.sin_family = AF_INET; |
@@ -339,23 +340,23 @@ send_icmp (const struct in_addr *my_ip, | |||
339 | ip_pkt.vers_ihl = 0x45; | 340 | ip_pkt.vers_ihl = 0x45; |
340 | ip_pkt.tos = 0; | 341 | ip_pkt.tos = 0; |
341 | ip_pkt.pkt_len = htons (sizeof (packet)); | 342 | ip_pkt.pkt_len = htons (sizeof (packet)); |
342 | ip_pkt.id = htons (256); | 343 | ip_pkt.id = htons (256); |
343 | ip_pkt.flags_frag_offset = 0; | 344 | ip_pkt.flags_frag_offset = 0; |
344 | ip_pkt.ttl = IPDEFTTL; | 345 | ip_pkt.ttl = IPDEFTTL; |
345 | ip_pkt.proto = IPPROTO_ICMP; | 346 | ip_pkt.proto = IPPROTO_ICMP; |
346 | ip_pkt.checksum = 0; | 347 | ip_pkt.checksum = 0; |
347 | ip_pkt.src_ip = my_ip->s_addr; | 348 | ip_pkt.src_ip = my_ip->s_addr; |
348 | ip_pkt.dst_ip = other->s_addr; | 349 | ip_pkt.dst_ip = other->s_addr; |
349 | ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, | 350 | ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, |
350 | sizeof (struct ip_header))); | 351 | sizeof (struct ip_header))); |
351 | memcpy (&packet[off], | 352 | memcpy (&packet[off], |
352 | &ip_pkt, | 353 | &ip_pkt, |
353 | sizeof (struct ip_header)); | 354 | sizeof (struct ip_header)); |
354 | off = sizeof (ip_pkt); | 355 | off = sizeof (ip_pkt); |
355 | 356 | ||
356 | /* icmp reply: time exceeded */ | 357 | /* icmp reply: time exceeded */ |
357 | icmp_ttl.type = ICMP_TIME_EXCEEDED; | 358 | icmp_ttl.type = ICMP_TIME_EXCEEDED; |
358 | icmp_ttl.code = 0; | 359 | icmp_ttl.code = 0; |
359 | icmp_ttl.checksum = 0; | 360 | icmp_ttl.checksum = 0; |
360 | icmp_ttl.unused = 0; | 361 | icmp_ttl.unused = 0; |
361 | memcpy (&packet[off], | 362 | memcpy (&packet[off], |
@@ -367,7 +368,7 @@ send_icmp (const struct in_addr *my_ip, | |||
367 | ip_pkt.vers_ihl = 0x45; | 368 | ip_pkt.vers_ihl = 0x45; |
368 | ip_pkt.tos = 0; | 369 | ip_pkt.tos = 0; |
369 | ip_pkt.pkt_len = htons (sizeof (struct ip_header) + sizeof (struct icmp_echo_header)); | 370 | ip_pkt.pkt_len = htons (sizeof (struct ip_header) + sizeof (struct icmp_echo_header)); |
370 | ip_pkt.id = htons (256); | 371 | ip_pkt.id = htons (256); |
371 | ip_pkt.flags_frag_offset = 0; | 372 | ip_pkt.flags_frag_offset = 0; |
372 | ip_pkt.ttl = 1; /* real TTL would be 1 on a time exceeded packet */ | 373 | ip_pkt.ttl = 1; /* real TTL would be 1 on a time exceeded packet */ |
373 | ip_pkt.proto = IPPROTO_ICMP; | 374 | ip_pkt.proto = IPPROTO_ICMP; |
@@ -375,9 +376,9 @@ send_icmp (const struct in_addr *my_ip, | |||
375 | ip_pkt.dst_ip = dummy.s_addr; | 376 | ip_pkt.dst_ip = dummy.s_addr; |
376 | ip_pkt.checksum = 0; | 377 | ip_pkt.checksum = 0; |
377 | ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, | 378 | ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, |
378 | sizeof (struct ip_header))); | 379 | sizeof (struct ip_header))); |
379 | memcpy (&packet[off], | 380 | memcpy (&packet[off], |
380 | &ip_pkt, | 381 | &ip_pkt, |
381 | sizeof (struct ip_header)); | 382 | sizeof (struct ip_header)); |
382 | off += sizeof (struct ip_header); | 383 | off += sizeof (struct ip_header); |
383 | 384 | ||
@@ -385,17 +386,17 @@ send_icmp (const struct in_addr *my_ip, | |||
385 | icmp_echo.code = 0; | 386 | icmp_echo.code = 0; |
386 | icmp_echo.reserved = htonl (port); | 387 | icmp_echo.reserved = htonl (port); |
387 | icmp_echo.checksum = 0; | 388 | icmp_echo.checksum = 0; |
388 | icmp_echo.checksum = htons(calc_checksum((uint16_t*) &icmp_echo, | 389 | icmp_echo.checksum = htons(calc_checksum((uint16_t*) &icmp_echo, |
389 | sizeof (struct icmp_echo_header))); | 390 | sizeof (struct icmp_echo_header))); |
390 | memcpy (&packet[off], | 391 | memcpy (&packet[off], |
391 | &icmp_echo, | 392 | &icmp_echo, |
392 | sizeof(struct icmp_echo_header)); | 393 | sizeof(struct icmp_echo_header)); |
393 | 394 | ||
394 | /* no go back to calculate ICMP packet checksum */ | 395 | /* no go back to calculate ICMP packet checksum */ |
395 | off = sizeof (struct ip_header); | 396 | off = sizeof (struct ip_header); |
396 | icmp_ttl.checksum = htons(calc_checksum((uint16_t*) &packet[off], | 397 | icmp_ttl.checksum = htons(calc_checksum((uint16_t*) &packet[off], |
397 | sizeof (struct icmp_ttl_exceeded_header) + | 398 | sizeof (struct icmp_ttl_exceeded_header) + |
398 | sizeof (struct ip_header) + | 399 | sizeof (struct ip_header) + |
399 | sizeof (struct icmp_echo_header))); | 400 | sizeof (struct icmp_echo_header))); |
400 | memcpy (&packet[off], | 401 | memcpy (&packet[off], |
401 | &icmp_ttl, | 402 | &icmp_ttl, |
@@ -408,17 +409,17 @@ send_icmp (const struct in_addr *my_ip, | |||
408 | dst.sin_len = sizeof (struct sockaddr_in); | 409 | dst.sin_len = sizeof (struct sockaddr_in); |
409 | #endif | 410 | #endif |
410 | dst.sin_addr = *other; | 411 | dst.sin_addr = *other; |
411 | err = sendto(rawsock, | 412 | err = sendto(rawsock, |
412 | packet, | 413 | packet, |
413 | sizeof (packet), 0, | 414 | sizeof (packet), 0, |
414 | (struct sockaddr*)&dst, | 415 | (struct sockaddr*)&dst, |
415 | sizeof(dst)); | 416 | sizeof(dst)); |
416 | if (err < 0) | 417 | if (err < 0) |
417 | { | 418 | { |
418 | fprintf(stderr, | 419 | fprintf(stderr, |
419 | "sendto failed: %s\n", strerror(errno)); | 420 | "sendto failed: %s\n", strerror(errno)); |
420 | } | 421 | } |
421 | else if (sizeof (packet) != (size_t) err) | 422 | else if (sizeof (packet) != (size_t) err) |
422 | { | 423 | { |
423 | fprintf(stderr, | 424 | fprintf(stderr, |
424 | "Error: partial send of ICMP message\n"); | 425 | "Error: partial send of ICMP message\n"); |
@@ -444,7 +445,7 @@ make_raw_socket () | |||
444 | "Error opening RAW socket: %s\n", | 445 | "Error opening RAW socket: %s\n", |
445 | strerror (errno)); | 446 | strerror (errno)); |
446 | return -1; | 447 | return -1; |
447 | } | 448 | } |
448 | if (0 != setsockopt(ret, SOL_SOCKET, SO_BROADCAST, | 449 | if (0 != setsockopt(ret, SOL_SOCKET, SO_BROADCAST, |
449 | (char *)&one, sizeof(one))) | 450 | (char *)&one, sizeof(one))) |
450 | { | 451 | { |
@@ -499,14 +500,14 @@ main (int argc, char *const *argv) | |||
499 | return 1; | 500 | return 1; |
500 | } | 501 | } |
501 | port = (uint16_t) p; | 502 | port = (uint16_t) p; |
502 | if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy)) | 503 | if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy)) |
503 | { | 504 | { |
504 | fprintf (stderr, | 505 | fprintf (stderr, |
505 | "Internal error converting dummy IP to binary.\n"); | 506 | "Internal error converting dummy IP to binary.\n"); |
506 | return 2; | 507 | return 2; |
507 | } | 508 | } |
508 | if (-1 == (rawsock = make_raw_socket())) | 509 | if (-1 == (rawsock = make_raw_socket())) |
509 | return 2; | 510 | return 2; |
510 | uid = getuid (); | 511 | uid = getuid (); |
511 | if (0 != setresuid (uid, uid, uid)) | 512 | if (0 != setresuid (uid, uid, uid)) |
512 | { | 513 | { |