aboutsummaryrefslogtreecommitdiff
path: root/src/transport/gnunet-nat-server.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-02-05 08:49:50 +0000
committerChristian Grothoff <christian@grothoff.org>2010-02-05 08:49:50 +0000
commit4e98f95fda2aee5c1d1936eee5536c81e5aec7b6 (patch)
tree9b3e9e52326fa1d95da78c93c69e60f9f2ea1acf /src/transport/gnunet-nat-server.c
parenta16bb742d0655f2c1c9b6f91b4fbcb1509398f28 (diff)
downloadgnunet-4e98f95fda2aee5c1d1936eee5536c81e5aec7b6.tar.gz
gnunet-4e98f95fda2aee5c1d1936eee5536c81e5aec7b6.zip
fixed
Diffstat (limited to 'src/transport/gnunet-nat-server.c')
-rw-r--r--src/transport/gnunet-nat-server.c117
1 files changed, 65 insertions, 52 deletions
diff --git a/src/transport/gnunet-nat-server.c b/src/transport/gnunet-nat-server.c
index 143c4ed32..9eab289e0 100644
--- a/src/transport/gnunet-nat-server.c
+++ b/src/transport/gnunet-nat-server.c
@@ -41,15 +41,22 @@
41#include <netinet/ip_icmp.h> 41#include <netinet/ip_icmp.h>
42#include <netinet/in.h> 42#include <netinet/in.h>
43 43
44#define DEBUG 0
45
44/** 46/**
45 * Number of UDP ports to keep open. 47 * Number of UDP ports to keep open (typically >= 256).
46 */ 48 */
47#define NUM_UDP_PORTS 512 49#define NUM_UDP_PORTS 256
48 50
49/** 51/**
50 * How often do we send our UDP messages to keep ports open? 52 * Number of ICMP replies to send per message received (typically >= 1024)
51 */ 53 */
52#define UDP_SEND_FREQUENCY_MS 500 54#define NUM_ICMP_REPLIES 1024
55
56/**
57 * How often do we send our UDP messages to keep ports open? (typically < 100ms)
58 */
59#define UDP_SEND_FREQUENCY_MS 50
53 60
54/** 61/**
55 * Port we use for the dummy target. 62 * Port we use for the dummy target.
@@ -77,13 +84,6 @@ struct ip_packet
77 uint32_t dst_ip; 84 uint32_t dst_ip;
78}; 85};
79 86
80struct icmp_packet
81{
82 uint8_t type;
83 uint8_t code;
84 uint16_t checksum;
85 uint32_t reserved;
86};
87 87
88struct udp_packet 88struct udp_packet
89{ 89{
@@ -94,6 +94,17 @@ struct udp_packet
94}; 94};
95 95
96 96
97struct icmp_packet
98{
99 uint8_t type;
100 uint8_t code;
101 uint16_t checksum;
102 uint32_t reserved;
103 struct ip_packet ip;
104 struct udp_packet udp;
105};
106
107
97/** 108/**
98 * Structure of the data we tack on to the fake ICMP reply 109 * Structure of the data we tack on to the fake ICMP reply
99 * (last 4 bytes of the 64 bytes). 110 * (last 4 bytes of the 64 bytes).
@@ -216,9 +227,8 @@ send_icmp (const struct in_addr *my_ip,
216{ 227{
217 struct ip_packet ip_pkt; 228 struct ip_packet ip_pkt;
218 struct icmp_packet icmp_pkt; 229 struct icmp_packet icmp_pkt;
219 struct udp_packet udp_pkt;
220 struct sockaddr_in dst; 230 struct sockaddr_in dst;
221 char packet[sizeof (ip_pkt) + sizeof (icmp_pkt) + sizeof (udp_pkt)]; 231 char packet[sizeof (ip_pkt) + sizeof (icmp_pkt)];
222 size_t off; 232 size_t off;
223 int err; 233 int err;
224 234
@@ -245,35 +255,28 @@ send_icmp (const struct in_addr *my_ip,
245 icmp_pkt.code = ICMP_NET_UNREACH; 255 icmp_pkt.code = ICMP_NET_UNREACH;
246 icmp_pkt.reserved = 0; 256 icmp_pkt.reserved = 0;
247 icmp_pkt.checksum = 0; 257 icmp_pkt.checksum = 0;
248 icmp_pkt.checksum = htons(calc_checksum((uint16_t*)&icmp_pkt, sizeof (icmp_pkt)));
249 memcpy (&packet[off], &icmp_pkt, sizeof (icmp_pkt));
250 off += sizeof (icmp_pkt);
251 258
252 /* ip header of the presumably 'lost' udp packet */ 259 /* ip header of the presumably 'lost' udp packet */
253 memset(&ip_pkt, 0, sizeof (ip_pkt)); 260 icmp_pkt.ip.vers_ihl = 0x45;
254 ip_pkt.vers_ihl = 0x45; 261 icmp_pkt.ip.tos = 0;
255 ip_pkt.tos = 0;
256 /* no idea why i need to shift the bits here, but not on ip_pkt->pkt_len... */ 262 /* no idea why i need to shift the bits here, but not on ip_pkt->pkt_len... */
257 ip_pkt.pkt_len = (sizeof (ip_pkt) + sizeof (icmp_pkt)) << 8; 263 icmp_pkt.ip.pkt_len = (sizeof (ip_pkt) + sizeof (icmp_pkt)) << 8;
258 ip_pkt.id = 1; /* kernel sets proper value htons(ip_id_counter); */ 264 icmp_pkt.ip.id = 1; /* kernel sets proper value htons(ip_id_counter); */
259 ip_pkt.flags_frag_offset = 0; 265 icmp_pkt.ip.flags_frag_offset = 0;
260 ip_pkt.ttl = 1; /* real TTL would be 1 on a time exceeded packet */ 266 icmp_pkt.ip.ttl = 1; /* real TTL would be 1 on a time exceeded packet */
261 ip_pkt.proto = IPPROTO_UDP; 267 icmp_pkt.ip.proto = IPPROTO_UDP;
262 ip_pkt.src_ip = other->s_addr; 268 icmp_pkt.ip.src_ip = other->s_addr;
263 ip_pkt.dst_ip = dummy.s_addr; 269 icmp_pkt.ip.dst_ip = dummy.s_addr;
264 ip_pkt.checksum = 0; 270 icmp_pkt.ip.checksum = 0;
265 ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, sizeof (ip_pkt))); 271 icmp_pkt.ip.checksum = htons(calc_checksum((uint16_t*)&icmp_pkt.ip, sizeof (icmp_pkt.ip)));
266 memcpy (&packet[off], &ip_pkt, sizeof (ip_pkt)); 272 icmp_pkt.udp.source_port = htons (target_port_number);
267 off += sizeof (ip_pkt); 273 icmp_pkt.udp.dst_port = htons (NAT_TRAV_PORT);
268 274 icmp_pkt.udp.mlen_aka_reply_port_magic = htons (source_port_number);
269 memset(&udp_pkt, 0, sizeof (udp_pkt)); 275 icmp_pkt.udp.checksum_aka_my_magic = htons (target_port_number);
270 udp_pkt.source_port = htons (target_port_number); /* this one will be re-written by NAT */ 276 icmp_pkt.checksum = htons(calc_checksum((uint16_t*)&icmp_pkt, sizeof (icmp_pkt)));
271 udp_pkt.dst_port = htons (NAT_TRAV_PORT); 277 memcpy (&packet[off], &icmp_pkt, sizeof (icmp_pkt));
272 udp_pkt.mlen_aka_reply_port_magic = htons (source_port_number); 278 off += sizeof (icmp_pkt);
273 udp_pkt.checksum_aka_my_magic = htons (target_port_number); /* this one should be bounced back to me as 'reply_port_magic' */ 279
274 memcpy (&packet[off], &udp_pkt, sizeof (udp_pkt));
275 off += sizeof (udp_pkt);
276
277 memset (&dst, 0, sizeof (dst)); 280 memset (&dst, 0, sizeof (dst));
278 dst.sin_family = AF_INET; 281 dst.sin_family = AF_INET;
279 dst.sin_addr = *other; 282 dst.sin_addr = *other;
@@ -301,17 +304,19 @@ try_connect (const struct in_addr *my_ip,
301 uint16_t port_magic) 304 uint16_t port_magic)
302{ 305{
303 unsigned int i; 306 unsigned int i;
307#if DEBUG
304 char sbuf [INET_ADDRSTRLEN]; 308 char sbuf [INET_ADDRSTRLEN];
305 309
306 fprintf (stderr, 310 fprintf (stderr,
307 "Sending %u ICMPs to `%s' with reply magic %u\n", 311 "Sending %u ICMPs to `%s' with reply magic %u\n",
308 NUM_UDP_PORTS, 312 NUM_ICMP_REPLIES,
309 inet_ntop (AF_INET, 313 inet_ntop (AF_INET,
310 other, 314 other,
311 sbuf, 315 sbuf,
312 sizeof (sbuf)), 316 sizeof (sbuf)),
313 port_magic); 317 port_magic);
314 for (i=0;i<NUM_UDP_PORTS;i++) 318#endif
319 for (i=0;i<NUM_ICMP_REPLIES;i++)
315 send_icmp (my_ip, other, make_port(), port_magic); 320 send_icmp (my_ip, other, make_port(), port_magic);
316} 321}
317 322
@@ -328,7 +333,6 @@ process_icmp_response (const struct in_addr *my_ip,
328 uint16_t local_port; 333 uint16_t local_port;
329 struct ip_packet ip_pkt; 334 struct ip_packet ip_pkt;
330 struct icmp_packet icmp_pkt; 335 struct icmp_packet icmp_pkt;
331 struct udp_packet udp_pkt;
332 size_t off; 336 size_t off;
333 337
334 have = read (s, buf, sizeof (buf)); 338 have = read (s, buf, sizeof (buf));
@@ -340,8 +344,7 @@ process_icmp_response (const struct in_addr *my_ip,
340 /* What now? */ 344 /* What now? */
341 return; 345 return;
342 } 346 }
343 if (have != 2 * sizeof (struct ip_packet) + sizeof (struct icmp_packet) + 347 if (have != sizeof (struct ip_packet) + sizeof (struct icmp_packet))
344 sizeof (struct udp_packet))
345 { 348 {
346 fprintf (stderr, 349 fprintf (stderr,
347 "Received ICMP message of unexpected size: %u bytes\n", 350 "Received ICMP message of unexpected size: %u bytes\n",
@@ -353,9 +356,6 @@ process_icmp_response (const struct in_addr *my_ip,
353 off += sizeof (ip_pkt); 356 off += sizeof (ip_pkt);
354 memcpy (&icmp_pkt, &buf[off], sizeof (icmp_pkt)); 357 memcpy (&icmp_pkt, &buf[off], sizeof (icmp_pkt));
355 off += sizeof (icmp_pkt); 358 off += sizeof (icmp_pkt);
356 off += sizeof (ip_pkt);
357 memcpy (&udp_pkt, &buf[off], sizeof (udp_pkt));
358 off += sizeof (struct udp_packet);
359 359
360 if ( (ip_pkt.proto == IPPROTO_ICMP) && 360 if ( (ip_pkt.proto == IPPROTO_ICMP) &&
361 (icmp_pkt.type == ICMP_DEST_UNREACH) && 361 (icmp_pkt.type == ICMP_DEST_UNREACH) &&
@@ -364,9 +364,19 @@ process_icmp_response (const struct in_addr *my_ip,
364 /* this is what is normal due to our UDP traffic */ 364 /* this is what is normal due to our UDP traffic */
365 return; 365 return;
366 } 366 }
367 if ( (ip_pkt.proto == IPPROTO_ICMP) &&
368 (icmp_pkt.type == ICMP_TIME_EXCEEDED) &&
369 (icmp_pkt.code == ICMP_NET_UNREACH) )
370 {
371 /* this is what we might see on loopback: this is the format
372 we as the server send out (the client uses 'ICMP_HOST_UNREACH');
373 Ignore! */
374 return;
375 }
376
367 if ( (ip_pkt.proto != IPPROTO_ICMP) || 377 if ( (ip_pkt.proto != IPPROTO_ICMP) ||
368 (icmp_pkt.type != ICMP_TIME_EXCEEDED) || 378 (icmp_pkt.type != ICMP_TIME_EXCEEDED) ||
369 (icmp_pkt.code != ICMP_NET_UNREACH) ) 379 (icmp_pkt.code != ICMP_HOST_UNREACH) )
370 { 380 {
371 /* Note the expected client response and not the normal network response */ 381 /* Note the expected client response and not the normal network response */
372 fprintf (stderr, 382 fprintf (stderr,
@@ -377,9 +387,10 @@ process_icmp_response (const struct in_addr *my_ip,
377 return; 387 return;
378 } 388 }
379 memcpy(&sip, &ip_pkt.src_ip, sizeof (sip)); 389 memcpy(&sip, &ip_pkt.src_ip, sizeof (sip));
380 reply_magic = ntohs (udp_pkt.checksum_aka_my_magic); 390 reply_magic = ntohs (icmp_pkt.udp.checksum_aka_my_magic);
381 my_magic = ntohs (udp_pkt.mlen_aka_reply_port_magic); 391 my_magic = ntohs (icmp_pkt.udp.mlen_aka_reply_port_magic);
382 local_port = ntohs (udp_pkt.source_port); 392 local_port = ntohs (icmp_pkt.udp.source_port);
393#if DEBUG
383 fprintf (stderr, 394 fprintf (stderr,
384 "Received ICMP from `%s' with outgoing port %u, listen port %u and incoming port hint for other peer %u\n", 395 "Received ICMP from `%s' with outgoing port %u, listen port %u and incoming port hint for other peer %u\n",
385 inet_ntop (AF_INET, 396 inet_ntop (AF_INET,
@@ -389,6 +400,7 @@ process_icmp_response (const struct in_addr *my_ip,
389 my_magic, 400 my_magic,
390 local_port, 401 local_port,
391 reply_magic); 402 reply_magic);
403#endif
392 if (my_magic == 0) 404 if (my_magic == 0)
393 { 405 {
394 try_connect (my_ip, &sip, reply_magic); 406 try_connect (my_ip, &sip, reply_magic);
@@ -522,11 +534,12 @@ main (int argc, char *const *argv)
522 process_icmp_response (&external, icmpsock); 534 process_icmp_response (&external, icmpsock);
523 continue; 535 continue;
524 } 536 }
537#if DEBUG
525 fprintf (stderr, 538 fprintf (stderr,
526 "Sending UDP message to %s:%u\n", 539 "Sending UDP message to %s:%u\n",
527 argv[2], 540 argv[2],
528 NAT_TRAV_PORT); 541 NAT_TRAV_PORT);
529 542#endif
530 if (-1 == sendto (udpsocks[pos], 543 if (-1 == sendto (udpsocks[pos],
531 NULL, 0, 0, 544 NULL, 0, 0,
532 (struct sockaddr*) &dst, sizeof (dst))) 545 (struct sockaddr*) &dst, sizeof (dst)))