aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/transport/gnunet-nat-server-windows.c28
-rw-r--r--src/transport/gnunet-nat-server.c238
2 files changed, 190 insertions, 76 deletions
diff --git a/src/transport/gnunet-nat-server-windows.c b/src/transport/gnunet-nat-server-windows.c
index 7dee15296..bd757299e 100644
--- a/src/transport/gnunet-nat-server-windows.c
+++ b/src/transport/gnunet-nat-server-windows.c
@@ -60,6 +60,11 @@
60#define VERBOSE 0 60#define VERBOSE 0
61 61
62/** 62/**
63 * Must match IP given in the client.
64 */
65#define DUMMY_IP "192.0.2.86"
66
67/**
63 * TTL to use for our outgoing messages. 68 * TTL to use for our outgoing messages.
64 */ 69 */
65#define IPDEFTTL 64 70#define IPDEFTTL 64
@@ -69,11 +74,6 @@
69#define ICMP_TIME_EXCEEDED 11 /* Time Exceeded */ 74#define ICMP_TIME_EXCEEDED 11 /* Time Exceeded */
70 75
71/** 76/**
72 * Must match IP given in the client.
73 */
74#define DUMMY_IP "192.0.2.86"
75
76/**
77 * How often do we send our ICMP messages to receive replies? 77 * How often do we send our ICMP messages to receive replies?
78 */ 78 */
79#define ICMP_SEND_FREQUENCY_MS 500 79#define ICMP_SEND_FREQUENCY_MS 500
@@ -303,7 +303,6 @@ process_icmp_response ()
303 struct udp_packet udp_pkt; 303 struct udp_packet udp_pkt;
304 size_t off; 304 size_t off;
305 int have_port; 305 int have_port;
306 int have_udp;
307 uint32_t port; 306 uint32_t port;
308 307
309 have = read (icmpsock, buf, sizeof (buf)); 308 have = read (icmpsock, buf, sizeof (buf));
@@ -350,7 +349,6 @@ process_icmp_response ()
350 sizeof (sip)); 349 sizeof (sip));
351 memcpy (&ip_pkt, &buf[off], sizeof (ip_pkt)); 350 memcpy (&ip_pkt, &buf[off], sizeof (ip_pkt));
352 off += sizeof (ip_pkt); 351 off += sizeof (ip_pkt);
353 have_udp = (ip_pkt.proto == IPPROTO_UDP);
354 352
355 if (have_port) 353 if (have_port)
356 { 354 {
@@ -369,7 +367,7 @@ process_icmp_response ()
369 buf, 367 buf,
370 port); 368 port);
371 } 369 }
372 else if (have_udp) 370 else if (ip_pkt.proto == IPPROTO_UDP)
373 { 371 {
374 memcpy(&udp_pkt, 372 memcpy(&udp_pkt,
375 &buf[off], 373 &buf[off],
@@ -383,7 +381,7 @@ process_icmp_response ()
383 fprintf (stdout, 381 fprintf (stdout,
384 "%s:%d\n", 382 "%s:%d\n",
385 buf, 383 buf,
386 ntohs((int)udp_pkt.length)); 384 ntohs((uint16_t)udp_pkt.length));
387 } 385 }
388 else 386 else
389 { 387 {
@@ -403,6 +401,8 @@ process_icmp_response ()
403 401
404/** 402/**
405 * Create an ICMP raw socket for reading. 403 * Create an ICMP raw socket for reading.
404 *
405 * @return INVALID_SOCKET on error
406 */ 406 */
407static SOCKET 407static SOCKET
408make_icmp_socket () 408make_icmp_socket ()
@@ -415,7 +415,7 @@ make_icmp_socket ()
415 fprintf (stderr, 415 fprintf (stderr,
416 "Error opening RAW socket: %s\n", 416 "Error opening RAW socket: %s\n",
417 strerror (errno)); 417 strerror (errno));
418 return -1; 418 return INVALID_SOCKET;
419 } 419 }
420 return ret; 420 return ret;
421} 421}
@@ -423,6 +423,8 @@ make_icmp_socket ()
423 423
424/** 424/**
425 * Create an ICMP raw socket for writing. 425 * Create an ICMP raw socket for writing.
426 *
427 * @return INVALID_SOCKET on error
426 */ 428 */
427static SOCKET 429static SOCKET
428make_raw_socket () 430make_raw_socket ()
@@ -498,11 +500,11 @@ main (int argc,
498 fprintf (stderr, "Failed to find Winsock 2.1 or better.\n"); 500 fprintf (stderr, "Failed to find Winsock 2.1 or better.\n");
499 return 2; 501 return 2;
500 } 502 }
501 if (-1 == (icmpsock = make_icmp_socket())) 503 if (INVALID_SOCKET == (icmpsock = make_icmp_socket()))
502 { 504 {
503 return 3; 505 return 3;
504 } 506 }
505 if (-1 == (make_raw_socket())) 507 if (INVALID_SOCKET == (make_raw_socket()))
506 { 508 {
507 closesocket (icmpsock); 509 closesocket (icmpsock);
508 return 3; 510 return 3;
@@ -513,7 +515,7 @@ main (int argc,
513 FD_SET (icmpsock, &rs); 515 FD_SET (icmpsock, &rs);
514 tv.tv_sec = 0; 516 tv.tv_sec = 0;
515 tv.tv_usec = ICMP_SEND_FREQUENCY_MS * 1000; 517 tv.tv_usec = ICMP_SEND_FREQUENCY_MS * 1000;
516 if (0 != select (icmpsock + 1, &rs, NULL, NULL, &tv)) 518 if (-1 == select (icmpsock + 1, &rs, NULL, NULL, &tv))
517 { 519 {
518 if (errno == EINTR) 520 if (errno == EINTR)
519 continue; 521 continue;
diff --git a/src/transport/gnunet-nat-server.c b/src/transport/gnunet-nat-server.c
index ff1037a2a..1328f28b1 100644
--- a/src/transport/gnunet-nat-server.c
+++ b/src/transport/gnunet-nat-server.c
@@ -59,36 +59,85 @@
59#include <netinet/in.h> 59#include <netinet/in.h>
60 60
61/** 61/**
62 * Should we print some debug output?
63 */
64#define VERBOSE 0
65
66/**
62 * Must match IP given in the client. 67 * Must match IP given in the client.
63 */ 68 */
64#define DUMMY_IP "192.0.2.86" 69#define DUMMY_IP "192.0.2.86"
65 70
66#define VERBOSE 0
67
68/** 71/**
69 * How often do we send our ICMP messages to receive replies? 72 * How often do we send our ICMP messages to receive replies?
70 */ 73 */
71#define ICMP_SEND_FREQUENCY_MS 500 74#define ICMP_SEND_FREQUENCY_MS 500
72 75
76/**
77 * IPv4 header.
78 */
73struct ip_packet 79struct ip_packet
74{ 80{
81
82 /**
83 * Version (4 bits) + Internet header length (4 bits)
84 */
75 uint8_t vers_ihl; 85 uint8_t vers_ihl;
86
87 /**
88 * Type of service
89 */
76 uint8_t tos; 90 uint8_t tos;
91
92 /**
93 * Total length
94 */
77 uint16_t pkt_len; 95 uint16_t pkt_len;
96
97 /**
98 * Identification
99 */
78 uint16_t id; 100 uint16_t id;
101
102 /**
103 * Flags (3 bits) + Fragment offset (13 bits)
104 */
79 uint16_t flags_frag_offset; 105 uint16_t flags_frag_offset;
106
107 /**
108 * Time to live
109 */
80 uint8_t ttl; 110 uint8_t ttl;
111
112 /**
113 * Protocol
114 */
81 uint8_t proto; 115 uint8_t proto;
116
117 /**
118 * Header checksum
119 */
82 uint16_t checksum; 120 uint16_t checksum;
121
122 /**
123 * Source address
124 */
83 uint32_t src_ip; 125 uint32_t src_ip;
126
127 /**
128 * Destination address
129 */
84 uint32_t dst_ip; 130 uint32_t dst_ip;
85}; 131};
86 132
87struct icmp_packet 133struct icmp_packet
88{ 134{
89 uint8_t type; 135 uint8_t type;
136
90 uint8_t code; 137 uint8_t code;
138
91 uint16_t checksum; 139 uint16_t checksum;
140
92 uint32_t reserved; 141 uint32_t reserved;
93}; 142};
94 143
@@ -101,12 +150,29 @@ struct udp_packet
101 uint32_t length; 150 uint32_t length;
102}; 151};
103 152
153/**
154 * Socket we use to receive "fake" ICMP replies.
155 */
104static int icmpsock; 156static int icmpsock;
105 157
158/**
159 * Socket we use to send our ICMP requests.
160 */
106static int rawsock; 161static int rawsock;
107 162
163/**
164 * Target "dummy" address.
165 */
108static struct in_addr dummy; 166static struct in_addr dummy;
109 167
168
169/**
170 * CRC-16 for IP/ICMP headers.
171 *
172 * @param data what to calculate the CRC over
173 * @param bytes number of bytes in data (must be multiple of 2)
174 * @return the CRC 16.
175 */
110static uint16_t 176static uint16_t
111calc_checksum(const uint16_t *data, 177calc_checksum(const uint16_t *data,
112 unsigned int bytes) 178 unsigned int bytes)
@@ -123,19 +189,6 @@ calc_checksum(const uint16_t *data,
123} 189}
124 190
125 191
126static void
127make_echo (const struct in_addr *src_ip,
128 struct icmp_packet *echo)
129{
130 memset(echo, 0, sizeof(struct icmp_packet));
131 echo->type = ICMP_ECHO;
132 echo->code = 0;
133 echo->reserved = 0;
134 echo->checksum = 0;
135 echo->checksum = htons(calc_checksum((uint16_t*)echo, sizeof (struct icmp_packet)));
136}
137
138
139/** 192/**
140 * Send an ICMP message to the dummy IP. 193 * Send an ICMP message to the dummy IP.
141 * 194 *
@@ -167,7 +220,16 @@ send_icmp_echo (const struct in_addr *my_ip)
167 ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, sizeof (ip_pkt))); 220 ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, sizeof (ip_pkt)));
168 memcpy (packet, &ip_pkt, sizeof (ip_pkt)); 221 memcpy (packet, &ip_pkt, sizeof (ip_pkt));
169 off += sizeof (ip_pkt); 222 off += sizeof (ip_pkt);
223
224 icmp_echo.type = ICMP_ECHO;
225 icmp_echo.code = 0;
226 icmp_echo.reserved = 0;
227 icmp_echo.checksum = 0;
228 icmp_echo.checksum = htons(calc_checksum((uint16_t*)&icmp_echo,
229 sizeof (struct icmp_packet)));
230
170 make_echo (my_ip, &icmp_echo); 231 make_echo (my_ip, &icmp_echo);
232
171 memcpy (&packet[off], &icmp_echo, sizeof (icmp_echo)); 233 memcpy (&packet[off], &icmp_echo, sizeof (icmp_echo));
172 off += sizeof (icmp_echo); 234 off += sizeof (icmp_echo);
173 235
@@ -193,6 +255,9 @@ send_icmp_echo (const struct in_addr *my_ip)
193} 255}
194 256
195 257
258/**
259 * We've received an ICMP response. Process it.
260 */
196static void 261static void
197process_icmp_response () 262process_icmp_response ()
198{ 263{
@@ -204,7 +269,6 @@ process_icmp_response ()
204 struct udp_packet udp_pkt; 269 struct udp_packet udp_pkt;
205 size_t off; 270 size_t off;
206 int have_port; 271 int have_port;
207 int have_udp;
208 uint32_t port; 272 uint32_t port;
209 273
210 have = read (icmpsock, buf, sizeof (buf)); 274 have = read (icmpsock, buf, sizeof (buf));
@@ -216,7 +280,11 @@ process_icmp_response ()
216 return; 280 return;
217 } 281 }
218 have_port = 0; 282 have_port = 0;
219 283#if VERBOSE
284 fprintf (stderr,
285 "Received message of %u bytes\n",
286 (unsigned int) have);
287#endif
220 if (have == sizeof (struct ip_packet) *2 + sizeof (struct icmp_packet) * 2 + sizeof(uint32_t)) 288 if (have == sizeof (struct ip_packet) *2 + sizeof (struct icmp_packet) * 2 + sizeof(uint32_t))
221 { 289 {
222 have_port = 1; 290 have_port = 1;
@@ -245,50 +313,54 @@ process_icmp_response ()
245 memcpy(&sip, 313 memcpy(&sip,
246 &ip_pkt.src_ip, 314 &ip_pkt.src_ip,
247 sizeof (sip)); 315 sizeof (sip));
248
249 memcpy (&ip_pkt, &buf[off], sizeof (ip_pkt)); 316 memcpy (&ip_pkt, &buf[off], sizeof (ip_pkt));
250 off += sizeof (ip_pkt); 317 off += sizeof (ip_pkt);
251 318
252 have_udp = 0;
253 if (ip_pkt.proto == IPPROTO_UDP)
254 {
255 have_udp = 1;
256 }
257
258 if (have_port) 319 if (have_port)
259 { 320 {
260 memcpy(&port, &buf[sizeof (struct ip_packet) *2 + sizeof (struct icmp_packet) * 2], sizeof(uint32_t)); 321 memcpy(&port,
322 &buf[sizeof (struct ip_packet) *2 + sizeof (struct icmp_packet) * 2],
323 sizeof(uint32_t));
261 port = ntohs(port); 324 port = ntohs(port);
262 fprintf (stdout, 325 fprintf (stdout,
263 "%s:%d\n", 326 "%s:%d\n",
264 inet_ntop (AF_INET, 327 inet_ntop (AF_INET,
265 &sip, 328 &sip,
266 buf, 329 buf,
267 sizeof (buf)), port); 330 sizeof (buf)),
331 port);
268 } 332 }
269 else if (have_udp) 333 else if (ip_pkt.proto == IPPROTO_UDP)
270 { 334 {
271 memcpy(&udp_pkt, &buf[off], sizeof(udp_pkt)); 335 memcpy(&udp_pkt,
336 &buf[off],
337 sizeof(udp_pkt));
272 fprintf (stdout, 338 fprintf (stdout,
273 "%s:%d\n", 339 "%s:%d\n",
274 inet_ntop (AF_INET, 340 inet_ntop (AF_INET,
275 &sip, 341 &sip,
276 buf, 342 buf,
277 sizeof (buf)), ntohl(udp_pkt.length)); 343 sizeof (buf)),
344 ntohs((uint16_t) udp_pkt.length));
278 } 345 }
279 else 346 else
280 { 347 {
281 fprintf (stdout, 348 fprintf (stdout,
282 "%s\n", 349 "%s\n",
283 inet_ntop (AF_INET, 350 inet_ntop (AF_INET,
284 &sip, 351 &sip,
285 buf, 352 buf,
286 sizeof (buf))); 353 sizeof (buf)));
287 } 354 }
288 fflush (stdout); 355 fflush (stdout);
289} 356}
290 357
291 358
359/**
360 * Create an ICMP raw socket for reading.
361 *
362 * @return -1 on error
363 */
292static int 364static int
293make_icmp_socket () 365make_icmp_socket ()
294{ 366{
@@ -315,6 +387,11 @@ make_icmp_socket ()
315} 387}
316 388
317 389
390/**
391 * Create an ICMP raw socket for writing.
392 *
393 * @return -1 on error
394 */
318static int 395static int
319make_raw_socket () 396make_raw_socket ()
320{ 397{
@@ -329,40 +406,42 @@ make_raw_socket ()
329 strerror (errno)); 406 strerror (errno));
330 return -1; 407 return -1;
331 } 408 }
332 if (setsockopt(ret, SOL_SOCKET, SO_BROADCAST, 409 if (setsockopt(ret,
333 (char *)&one, sizeof(one)) == -1) 410 SOL_SOCKET,
334 fprintf(stderr, 411 SO_BROADCAST,
335 "setsockopt failed: %s\n", 412 (char *)&one,
336 strerror (errno)); 413 sizeof(one)) == -1)
337 if (setsockopt(ret, IPPROTO_IP, IP_HDRINCL, 414 {
415 fprintf(stderr,
416 "setsockopt failed: %s\n",
417 strerror (errno));
418 close (ret);
419 return -1;
420 }
421 if (setsockopt(ret,
422 IPPROTO_IP,
423 IP_HDRINCL,
338 (char *)&one, sizeof(one)) == -1) 424 (char *)&one, sizeof(one)) == -1)
339 fprintf(stderr, 425 {
340 "setsockopt failed: %s\n", 426 fprintf(stderr,
341 strerror (errno)); 427 "setsockopt failed: %s\n",
428 strerror (errno));
429 close (ret);
430 return -1;
431 }
342 return ret; 432 return ret;
343} 433}
344 434
345 435
346int 436int
347main (int argc, char *const *argv) 437main (int argc,
438 char *const *argv)
348{ 439{
349 struct in_addr external; 440 struct in_addr external;
350 fd_set rs; 441 fd_set rs;
351 struct timeval tv; 442 struct timeval tv;
352 uid_t uid; 443 uid_t uid;
353 444
354 if (-1 == (icmpsock = make_icmp_socket()))
355 return 1;
356 if (-1 == (rawsock = make_raw_socket()))
357 {
358 close (icmpsock);
359 return 1;
360 }
361 uid = getuid ();
362 if (0 != setresuid (uid, uid, uid))
363 fprintf (stderr,
364 "Failed to setresuid: %s\n",
365 strerror (errno));
366 if (argc != 2) 445 if (argc != 2)
367 { 446 {
368 fprintf (stderr, 447 fprintf (stderr,
@@ -376,19 +455,52 @@ main (int argc, char *const *argv)
376 strerror (errno)); 455 strerror (errno));
377 return 1; 456 return 1;
378 } 457 }
379 if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy)) abort (); 458 if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy))
459 {
460 fprintf (stderr,
461 "Internal error converting dummy IP to binary.\n");
462 return 2;
463 }
464 if (-1 == (icmpsock = make_icmp_socket()))
465 {
466 return 3;
467 }
468 if (-1 == (rawsock = make_raw_socket()))
469 {
470 close (icmpsock);
471 return 3;
472 }
473 uid = getuid ();
474 if (0 != setresuid (uid, uid, uid))
475 {
476 fprintf (stderr,
477 "Failed to setresuid: %s\n",
478 strerror (errno));
479 /* not critical, continue anyway */
480 }
380 while (1) 481 while (1)
381 { 482 {
382 FD_ZERO (&rs); 483 FD_ZERO (&rs);
383 FD_SET (icmpsock, &rs); 484 FD_SET (icmpsock, &rs);
384 tv.tv_sec = 0; 485 tv.tv_sec = 0;
385 tv.tv_usec = ICMP_SEND_FREQUENCY_MS * 1000; 486 tv.tv_usec = ICMP_SEND_FREQUENCY_MS * 1000;
386 select (icmpsock + 1, &rs, NULL, NULL, &tv); 487 if (-1 == select (icmpsock + 1, &rs, NULL, NULL, &tv))
488 {
489 if (errno == EINTR)
490 continue;
491 fprintf (stderr,
492 "select failed: %s\n",
493 strerror (errno));
494 break;
495 }
387 if (FD_ISSET (icmpsock, &rs)) 496 if (FD_ISSET (icmpsock, &rs))
388 process_icmp_response (); 497 process_icmp_response ();
389 send_icmp_echo (&external); 498 send_icmp_echo (&external);
390 } 499 }
391 return 0; 500 /* select failed (internal error or OS out of resources) */
501 close (icmpsock);
502 close (rawsock);
503 return 4;
392} 504}
393 505
394 506