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/transport/gnunet-nat-server.c | |
parent | a16bb742d0655f2c1c9b6f91b4fbcb1509398f28 (diff) | |
download | gnunet-4e98f95fda2aee5c1d1936eee5536c81e5aec7b6.tar.gz gnunet-4e98f95fda2aee5c1d1936eee5536c81e5aec7b6.zip |
fixed
Diffstat (limited to 'src/transport/gnunet-nat-server.c')
-rw-r--r-- | src/transport/gnunet-nat-server.c | 117 |
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 | ||
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))) |