aboutsummaryrefslogtreecommitdiff
path: root/src/transport/gnunet-nat-client.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-08-22 13:36:33 +0000
committerChristian Grothoff <christian@grothoff.org>2010-08-22 13:36:33 +0000
commitb4e21c6afcb6cd772c66b2c0ae3199f193c972c7 (patch)
tree10cf25bb37ee491ac5d083d93678944e0e510f1c /src/transport/gnunet-nat-client.c
parent1355ed0acd88356beccc25dfc710ef0d458b5b96 (diff)
downloadgnunet-b4e21c6afcb6cd772c66b2c0ae3199f193c972c7.tar.gz
gnunet-b4e21c6afcb6cd772c66b2c0ae3199f193c972c7.zip
audit
Diffstat (limited to 'src/transport/gnunet-nat-client.c')
-rw-r--r--src/transport/gnunet-nat-client.c101
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 */
73struct ip_header 74struct 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 */
130struct icmp_ttl_exceeded_header 131struct 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 */
176static struct in_addr dummy; 177static 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 */
191static uint16_t 192static uint16_t
192calc_checksum (const uint16_t *data, 193calc_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
214send_icmp_udp (const struct in_addr *my_ip, 215send_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 {