diff options
author | Christian Grothoff <christian@grothoff.org> | 2010-02-05 08:49:50 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2010-02-05 08:49:50 +0000 |
commit | 4e98f95fda2aee5c1d1936eee5536c81e5aec7b6 (patch) | |
tree | 9b3e9e52326fa1d95da78c93c69e60f9f2ea1acf /src | |
parent | a16bb742d0655f2c1c9b6f91b4fbcb1509398f28 (diff) | |
download | gnunet-4e98f95fda2aee5c1d1936eee5536c81e5aec7b6.tar.gz gnunet-4e98f95fda2aee5c1d1936eee5536c81e5aec7b6.zip |
fixed
Diffstat (limited to 'src')
-rw-r--r-- | src/transport/gnunet-nat-client.c | 138 | ||||
-rw-r--r-- | src/transport/gnunet-nat-server.c | 117 |
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 | |||
65 | struct ip_packet | 71 | struct 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 | ||
79 | struct icmp_packet | ||
80 | { | ||
81 | uint8_t type; | ||
82 | uint8_t code; | ||
83 | uint16_t checksum; | ||
84 | uint32_t reserved; | ||
85 | }; | ||
86 | |||
87 | struct udp_packet | 85 | struct 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 | 93 | struct 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 | */ | ||
100 | struct 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 | |||
114 | static int udpsocks[NUM_UDP_PORTS]; | 104 | static int udpsocks[NUM_UDP_PORTS]; |
115 | 105 | ||
116 | static uint16_t udpports[NUM_UDP_PORTS]; | 106 | static 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 | ||
80 | struct icmp_packet | ||
81 | { | ||
82 | uint8_t type; | ||
83 | uint8_t code; | ||
84 | uint16_t checksum; | ||
85 | uint32_t reserved; | ||
86 | }; | ||
87 | 87 | ||
88 | struct udp_packet | 88 | struct udp_packet |
89 | { | 89 | { |
@@ -94,6 +94,17 @@ struct udp_packet | |||
94 | }; | 94 | }; |
95 | 95 | ||
96 | 96 | ||
97 | struct 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))) |