aboutsummaryrefslogtreecommitdiff
path: root/src
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
parenta16bb742d0655f2c1c9b6f91b4fbcb1509398f28 (diff)
downloadgnunet-4e98f95fda2aee5c1d1936eee5536c81e5aec7b6.tar.gz
gnunet-4e98f95fda2aee5c1d1936eee5536c81e5aec7b6.zip
fixed
Diffstat (limited to 'src')
-rw-r--r--src/transport/gnunet-nat-client.c138
-rw-r--r--src/transport/gnunet-nat-server.c117
2 files changed, 130 insertions, 125 deletions
diff --git a/src/transport/gnunet-nat-client.c b/src/transport/gnunet-nat-client.c
index 0f7f041fb..fc88f8229 100644
--- a/src/transport/gnunet-nat-client.c
+++ b/src/transport/gnunet-nat-client.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
46/**
47 * Number of UDP ports to keep open (typically >= 256)
48 */
49#define NUM_UDP_PORTS 256
50
44/** 51/**
45 * Number of UDP ports to keep open. 52 * Number of ICMP replies to send per message received (typically >= 1024)
46 */ 53 */
47#define NUM_UDP_PORTS 512 54#define NUM_ICMP_REPLIES 1024
48 55
49/** 56/**
50 * How often do we send our UDP messages to keep ports open? 57 * How often do we send our UDP messages to keep ports open? (typically < 100ms)
51 */ 58 */
52#define UDP_SEND_FREQUENCY_MS 500 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.
@@ -61,7 +68,6 @@
61 */ 68 */
62#define MAX_TRIES 10 69#define MAX_TRIES 10
63 70
64
65struct ip_packet 71struct ip_packet
66{ 72{
67 uint8_t vers_ihl; 73 uint8_t vers_ihl;
@@ -76,14 +82,6 @@ struct ip_packet
76 uint32_t dst_ip; 82 uint32_t dst_ip;
77}; 83};
78 84
79struct icmp_packet
80{
81 uint8_t type;
82 uint8_t code;
83 uint16_t checksum;
84 uint32_t reserved;
85};
86
87struct udp_packet 85struct udp_packet
88{ 86{
89 uint16_t source_port; 87 uint16_t source_port;
@@ -92,25 +90,17 @@ struct udp_packet
92 uint16_t checksum_aka_my_magic; 90 uint16_t checksum_aka_my_magic;
93}; 91};
94 92
95 93struct icmp_packet
96/**
97 * Structure of the data we tack on to the fake ICMP reply
98 * (last 4 bytes of the 64 bytes).
99 */
100struct extra_packet
101{ 94{
102 /** 95 uint8_t type;
103 * if this is a reply to an icmp, what was the 'my_magic' 96 uint8_t code;
104 * value from the original icmp? 97 uint16_t checksum;
105 */ 98 uint32_t reserved;
106 uint16_t reply_port_magic; 99 struct ip_packet ip;
107 100 struct udp_packet udp;
108 /**
109 * magic value of the sender of this icmp message.
110 */
111 uint16_t my_magic;
112}; 101};
113 102
103
114static int udpsocks[NUM_UDP_PORTS]; 104static int udpsocks[NUM_UDP_PORTS];
115 105
116static uint16_t udpports[NUM_UDP_PORTS]; 106static uint16_t udpports[NUM_UDP_PORTS];
@@ -217,9 +207,8 @@ send_icmp (const struct in_addr *my_ip,
217{ 207{
218 struct ip_packet ip_pkt; 208 struct ip_packet ip_pkt;
219 struct icmp_packet icmp_pkt; 209 struct icmp_packet icmp_pkt;
220 struct udp_packet udp_pkt;
221 struct sockaddr_in dst; 210 struct sockaddr_in dst;
222 char packet[sizeof (ip_pkt) + sizeof (icmp_pkt) + sizeof (udp_pkt)]; 211 char packet[sizeof (ip_pkt) + sizeof (icmp_pkt)];
223 size_t off; 212 size_t off;
224 int err; 213 int err;
225 214
@@ -233,7 +222,7 @@ send_icmp (const struct in_addr *my_ip,
233 ip_pkt.flags_frag_offset = 0; 222 ip_pkt.flags_frag_offset = 0;
234 ip_pkt.ttl = IPDEFTTL; 223 ip_pkt.ttl = IPDEFTTL;
235 ip_pkt.proto = IPPROTO_ICMP; 224 ip_pkt.proto = IPPROTO_ICMP;
236 ip_pkt.checksum = 0; /* maybe the kernel helps us out..? */ 225 ip_pkt.checksum = 0;
237 ip_pkt.src_ip = my_ip->s_addr; 226 ip_pkt.src_ip = my_ip->s_addr;
238 ip_pkt.dst_ip = other->s_addr; 227 ip_pkt.dst_ip = other->s_addr;
239 ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, sizeof (ip_pkt))); 228 ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, sizeof (ip_pkt)));
@@ -243,40 +232,30 @@ send_icmp (const struct in_addr *my_ip,
243 /* icmp reply: time exceeded */ 232 /* icmp reply: time exceeded */
244 memset(&icmp_pkt, 0, sizeof(icmp_pkt)); 233 memset(&icmp_pkt, 0, sizeof(icmp_pkt));
245 icmp_pkt.type = ICMP_TIME_EXCEEDED; 234 icmp_pkt.type = ICMP_TIME_EXCEEDED;
246 icmp_pkt.code = ICMP_NET_UNREACH; 235 icmp_pkt.code = ICMP_HOST_UNREACH;
247 icmp_pkt.reserved = 0; 236 icmp_pkt.reserved = 0;
248 icmp_pkt.checksum = 0; 237 icmp_pkt.checksum = 0;
249 icmp_pkt.checksum = htons(calc_checksum((uint16_t*)&icmp_pkt, sizeof (icmp_pkt)));
250 memcpy (&packet[off], &icmp_pkt, sizeof (icmp_pkt));
251 off += sizeof (icmp_pkt);
252 238
253 /* ip header of the presumably 'lost' udp packet */ 239 /* ip header of the presumably 'lost' udp packet */
254 memset(&ip_pkt, 0, sizeof (ip_pkt)); 240 icmp_pkt.ip.vers_ihl = 0x45;
255 ip_pkt.vers_ihl = 0x45; 241 icmp_pkt.ip.tos = 0;
256 ip_pkt.tos = 0;
257 /* no idea why i need to shift the bits here, but not on ip_pkt->pkt_len... */ 242 /* no idea why i need to shift the bits here, but not on ip_pkt->pkt_len... */
258 ip_pkt.pkt_len = (sizeof (ip_pkt) + sizeof (icmp_pkt)) << 8; 243 icmp_pkt.ip.pkt_len = (sizeof (ip_pkt) + sizeof (icmp_pkt)) << 8;
259 ip_pkt.id = 1; /* kernel sets proper value htons(ip_id_counter); */ 244 icmp_pkt.ip.id = 1; /* kernel sets proper value htons(ip_id_counter); */
260 ip_pkt.flags_frag_offset = 0; 245 icmp_pkt.ip.flags_frag_offset = 0;
261 ip_pkt.ttl = 1; /* real TTL would be 1 on a time exceeded packet */ 246 icmp_pkt.ip.ttl = 1; /* real TTL would be 1 on a time exceeded packet */
262 ip_pkt.proto = IPPROTO_UDP; 247 icmp_pkt.ip.proto = IPPROTO_UDP;
263 ip_pkt.src_ip = other->s_addr; 248 icmp_pkt.ip.src_ip = other->s_addr;
264 ip_pkt.dst_ip = dummy.s_addr; 249 icmp_pkt.ip.dst_ip = dummy.s_addr;
265 ip_pkt.checksum = 0; 250 icmp_pkt.ip.checksum = 0;
266 ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, sizeof (ip_pkt))); 251 icmp_pkt.ip.checksum = htons(calc_checksum((uint16_t*)&icmp_pkt.ip, sizeof (icmp_pkt.ip)));
267 memcpy (&packet[off], &ip_pkt, sizeof (ip_pkt)); 252 icmp_pkt.udp.source_port = htons (target_port_number);
268 off += sizeof (ip_pkt); 253 icmp_pkt.udp.dst_port = htons (NAT_TRAV_PORT);
269 254 icmp_pkt.udp.mlen_aka_reply_port_magic = htons (source_port_number);
270 memset(&udp_pkt, 0, sizeof (udp_pkt)); 255 icmp_pkt.udp.checksum_aka_my_magic = htons (target_port_number);
271 udp_pkt.source_port = htons (target_port_number); 256 icmp_pkt.checksum = htons(calc_checksum((uint16_t*)&icmp_pkt, sizeof (icmp_pkt)));
272 udp_pkt.dst_port = htons (NAT_TRAV_PORT); 257 memcpy (&packet[off], &icmp_pkt, sizeof (icmp_pkt));
273 fprintf (stderr, 258 off += sizeof (icmp_pkt);
274 "** Generating ICMP with rpm %u\n",
275 target_port_number);
276 udp_pkt.mlen_aka_reply_port_magic = htons (source_port_number);
277 udp_pkt.checksum_aka_my_magic = htons (target_port_number);
278 memcpy (&packet[off], &udp_pkt, sizeof (udp_pkt));
279 off += sizeof (udp_pkt);
280 259
281 memset (&dst, 0, sizeof (dst)); 260 memset (&dst, 0, sizeof (dst));
282 dst.sin_family = AF_INET; 261 dst.sin_family = AF_INET;
@@ -309,13 +288,13 @@ try_connect (const struct in_addr *my_ip,
309 288
310 fprintf (stderr, 289 fprintf (stderr,
311 "Sending %u ICMPs to `%s' with reply magic %u\n", 290 "Sending %u ICMPs to `%s' with reply magic %u\n",
312 NUM_UDP_PORTS, 291 NUM_ICMP_REPLIES,
313 inet_ntop (AF_INET, 292 inet_ntop (AF_INET,
314 other, 293 other,
315 sbuf, 294 sbuf,
316 sizeof (sbuf)), 295 sizeof (sbuf)),
317 port_magic); 296 port_magic);
318 for (i=0;i<NUM_UDP_PORTS;i++) 297 for (i=0;i<NUM_ICMP_REPLIES;i++)
319 send_icmp (my_ip, other, make_port(), port_magic); 298 send_icmp (my_ip, other, make_port(), port_magic);
320} 299}
321 300
@@ -332,7 +311,6 @@ process_icmp_response (const struct in_addr *my_ip,
332 uint16_t local_port; 311 uint16_t local_port;
333 struct ip_packet ip_pkt; 312 struct ip_packet ip_pkt;
334 struct icmp_packet icmp_pkt; 313 struct icmp_packet icmp_pkt;
335 struct udp_packet udp_pkt;
336 size_t off; 314 size_t off;
337 315
338 have = read (s, buf, sizeof (buf)); 316 have = read (s, buf, sizeof (buf));
@@ -344,8 +322,7 @@ process_icmp_response (const struct in_addr *my_ip,
344 /* What now? */ 322 /* What now? */
345 return; 323 return;
346 } 324 }
347 if (have != sizeof (struct ip_packet) *2 + sizeof (struct icmp_packet) + 325 if (have != sizeof (struct ip_packet) + sizeof (struct icmp_packet))
348 sizeof (struct udp_packet))
349 { 326 {
350 fprintf (stderr, 327 fprintf (stderr,
351 "Received ICMP message of unexpected size: %u bytes\n", 328 "Received ICMP message of unexpected size: %u bytes\n",
@@ -357,9 +334,6 @@ process_icmp_response (const struct in_addr *my_ip,
357 off += sizeof (ip_pkt); 334 off += sizeof (ip_pkt);
358 memcpy (&icmp_pkt, &buf[off], sizeof (icmp_pkt)); 335 memcpy (&icmp_pkt, &buf[off], sizeof (icmp_pkt));
359 off += sizeof (icmp_pkt); 336 off += sizeof (icmp_pkt);
360 off += sizeof (ip_pkt);
361 memcpy (&udp_pkt, &buf[off], sizeof (udp_pkt));
362 off += sizeof (struct udp_packet);
363 337
364 if ( (ip_pkt.proto == IPPROTO_ICMP) && 338 if ( (ip_pkt.proto == IPPROTO_ICMP) &&
365 (icmp_pkt.type == ICMP_DEST_UNREACH) && 339 (icmp_pkt.type == ICMP_DEST_UNREACH) &&
@@ -368,31 +342,43 @@ process_icmp_response (const struct in_addr *my_ip,
368 /* this is what is normal due to our UDP traffic */ 342 /* this is what is normal due to our UDP traffic */
369 return; 343 return;
370 } 344 }
345 if ( (ip_pkt.proto == IPPROTO_ICMP) &&
346 (icmp_pkt.type == ICMP_TIME_EXCEEDED) &&
347 (icmp_pkt.code == ICMP_HOST_UNREACH) )
348 {
349 /* this is what we might see on loopback: this is the format
350 we as the client send out (the host uses 'ICMP_NET_UNREACH');
351 Ignore! */
352 return;
353 }
371 if ( (ip_pkt.proto != IPPROTO_ICMP) || 354 if ( (ip_pkt.proto != IPPROTO_ICMP) ||
372 (icmp_pkt.type != ICMP_TIME_EXCEEDED) || 355 (icmp_pkt.type != ICMP_TIME_EXCEEDED) ||
373 (icmp_pkt.code != ICMP_NET_UNREACH) ) 356 (icmp_pkt.code != ICMP_NET_UNREACH) )
374 { 357 {
375 /* Note the expected client response and not the normal network response */ 358 /* Note the expected client response and not the normal network response */
359#if DEBUG
376 fprintf (stderr, 360 fprintf (stderr,
377 "Received unexpected ICMP message contents (%u, %u, %u), ignoring\n", 361 "Received unexpected ICMP message contents (%u, %u, %u), ignoring\n",
378 ip_pkt.proto, 362 ip_pkt.proto,
379 icmp_pkt.type, 363 icmp_pkt.type,
380 icmp_pkt.code); 364 icmp_pkt.code);
365#endif
381 return; 366 return;
382 } 367 }
383 memcpy(&sip, &ip_pkt.src_ip, sizeof (sip)); 368 memcpy(&sip, &ip_pkt.src_ip, sizeof (sip));
384 reply_magic = ntohs (udp_pkt.checksum_aka_my_magic); 369 reply_magic = ntohs (icmp_pkt.udp.checksum_aka_my_magic);
385 my_magic = ntohs (udp_pkt.mlen_aka_reply_port_magic); 370 my_magic = ntohs (icmp_pkt.udp.mlen_aka_reply_port_magic);
386 local_port = ntohs (udp_pkt.source_port); 371 local_port = ntohs (icmp_pkt.udp.source_port);
387 if (my_magic == 0) 372 if (my_magic == 0)
388 { 373 {
389#if 0 374#if DEBUG
390 /* we get these a lot during loopback testing... */ 375 /* we get these a lot during loopback testing... */
391 fprintf (stderr, 376 fprintf (stderr,
392 "Received ICMP without hint as to which port worked, dropping\n"); 377 "Received ICMP without hint as to which port worked, dropping\n");
393#endif 378#endif
394 return; 379 return;
395 } 380 }
381#if DEBUG
396 fprintf (stderr, 382 fprintf (stderr,
397 "Received ICMP from `%s' with outgoing port %u, listen port %u and incoming for other peer %u\n", 383 "Received ICMP from `%s' with outgoing port %u, listen port %u and incoming for other peer %u\n",
398 inet_ntop (AF_INET, 384 inet_ntop (AF_INET,
@@ -402,6 +388,7 @@ process_icmp_response (const struct in_addr *my_ip,
402 my_magic, 388 my_magic,
403 local_port, 389 local_port,
404 reply_magic); 390 reply_magic);
391#endif
405 if (my_magic == 0) 392 if (my_magic == 0)
406 { 393 {
407 try_connect (my_ip, &sip, reply_magic); 394 try_connect (my_ip, &sip, reply_magic);
@@ -417,6 +404,7 @@ process_icmp_response (const struct in_addr *my_ip,
417 my_magic, 404 my_magic,
418 local_port); 405 local_port);
419 /* technically, we're done here! */ 406 /* technically, we're done here! */
407 exit (0);
420 } 408 }
421} 409}
422 410
@@ -538,10 +526,12 @@ main (int argc, char *const *argv)
538 process_icmp_response (&external, icmpsock); 526 process_icmp_response (&external, icmpsock);
539 continue; 527 continue;
540 } 528 }
529#if DEBUG
541 fprintf (stderr, 530 fprintf (stderr,
542 "Sending UDP message to %s:%u\n", 531 "Sending UDP message to %s:%u\n",
543 argv[3], 532 argv[3],
544 NAT_TRAV_PORT); 533 NAT_TRAV_PORT);
534#endif
545 if (-1 == sendto (udpsocks[pos], 535 if (-1 == sendto (udpsocks[pos],
546 NULL, 0, 0, 536 NULL, 0, 0,
547 (struct sockaddr*) &dst, sizeof (dst))) 537 (struct sockaddr*) &dst, sizeof (dst)))
@@ -553,10 +543,12 @@ main (int argc, char *const *argv)
553 udpsocks[pos] = make_udp_socket (&udpports[pos]); 543 udpsocks[pos] = make_udp_socket (&udpports[pos]);
554 } 544 }
555 p = make_port (); 545 p = make_port ();
546#if DEBUG
556 fprintf (stderr, 547 fprintf (stderr,
557 "Sending fake ICMP message to %s:%u\n", 548 "Sending fake ICMP message to %s:%u\n",
558 argv[1], 549 argv[1],
559 p); 550 p);
551#endif
560 send_icmp (&external, 552 send_icmp (&external,
561 &target, 553 &target,
562 p, 554 p,
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)))