aboutsummaryrefslogtreecommitdiff
path: root/src/nat/gnunet-helper-nat-server.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nat/gnunet-helper-nat-server.c')
-rw-r--r--src/nat/gnunet-helper-nat-server.c401
1 files changed, 169 insertions, 232 deletions
diff --git a/src/nat/gnunet-helper-nat-server.c b/src/nat/gnunet-helper-nat-server.c
index 945c98735..636ae6003 100644
--- a/src/nat/gnunet-helper-nat-server.c
+++ b/src/nat/gnunet-helper-nat-server.c
@@ -212,17 +212,16 @@ static struct in_addr dummy;
212 * @return the CRC 16. 212 * @return the CRC 16.
213 */ 213 */
214static uint16_t 214static uint16_t
215calc_checksum(const uint16_t *data, 215calc_checksum (const uint16_t * data, unsigned int bytes)
216 unsigned int bytes)
217{ 216{
218 uint32_t sum; 217 uint32_t sum;
219 unsigned int i; 218 unsigned int i;
220 219
221 sum = 0; 220 sum = 0;
222 for (i=0;i<bytes/2;i++) 221 for (i = 0; i < bytes / 2; i++)
223 sum += data[i]; 222 sum += data[i];
224 sum = (sum & 0xffff) + (sum >> 16); 223 sum = (sum & 0xffff) + (sum >> 16);
225 sum = htons(0xffff - sum); 224 sum = htons (0xffff - sum);
226 return sum; 225 return sum;
227} 226}
228 227
@@ -253,22 +252,18 @@ send_icmp_echo (const struct in_addr *my_ip)
253 ip_pkt.checksum = 0; 252 ip_pkt.checksum = 0;
254 ip_pkt.src_ip = my_ip->s_addr; 253 ip_pkt.src_ip = my_ip->s_addr;
255 ip_pkt.dst_ip = dummy.s_addr; 254 ip_pkt.dst_ip = dummy.s_addr;
256 ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, 255 ip_pkt.checksum = htons (calc_checksum ((uint16_t *) & ip_pkt,
257 sizeof (struct ip_header))); 256 sizeof (struct ip_header)));
258 memcpy (&packet[off], 257 memcpy (&packet[off], &ip_pkt, sizeof (struct ip_header));
259 &ip_pkt,
260 sizeof (struct ip_header));
261 off += sizeof (struct ip_header); 258 off += sizeof (struct ip_header);
262 259
263 icmp_echo.type = ICMP_ECHO; 260 icmp_echo.type = ICMP_ECHO;
264 icmp_echo.code = 0; 261 icmp_echo.code = 0;
265 icmp_echo.checksum = 0; 262 icmp_echo.checksum = 0;
266 icmp_echo.reserved = 0; 263 icmp_echo.reserved = 0;
267 icmp_echo.checksum = htons(calc_checksum((uint16_t*)&icmp_echo, 264 icmp_echo.checksum = htons (calc_checksum ((uint16_t *) & icmp_echo,
268 sizeof (struct icmp_echo_header))); 265 sizeof (struct icmp_echo_header)));
269 memcpy (&packet[off], 266 memcpy (&packet[off], &icmp_echo, sizeof (struct icmp_echo_header));
270 &icmp_echo,
271 sizeof (struct icmp_echo_header));
272 off += sizeof (struct icmp_echo_header); 267 off += sizeof (struct icmp_echo_header);
273 268
274 memset (&dst, 0, sizeof (dst)); 269 memset (&dst, 0, sizeof (dst));
@@ -277,22 +272,18 @@ send_icmp_echo (const struct in_addr *my_ip)
277 dst.sin_len = sizeof (struct sockaddr_in); 272 dst.sin_len = sizeof (struct sockaddr_in);
278#endif 273#endif
279 dst.sin_addr = dummy; 274 dst.sin_addr = dummy;
280 err = sendto(rawsock, 275 err = sendto (rawsock,
281 packet, off, 0, 276 packet, off, 0, (struct sockaddr *) &dst, sizeof (dst));
282 (struct sockaddr*)&dst,
283 sizeof(dst));
284 if (err < 0) 277 if (err < 0)
285 { 278 {
286#if VERBOSE 279#if VERBOSE
287 fprintf(stderr, 280 fprintf (stderr, "sendto failed: %s\n", strerror (errno));
288 "sendto failed: %s\n", strerror(errno));
289#endif 281#endif
290 } 282 }
291 else if (sizeof (packet) != err) 283 else if (sizeof (packet) != err)
292 { 284 {
293 fprintf(stderr, 285 fprintf (stderr, "Error: partial send of ICMP message\n");
294 "Error: partial send of ICMP message\n"); 286 }
295 }
296} 287}
297 288
298 289
@@ -312,22 +303,17 @@ send_udp ()
312#endif 303#endif
313 dst.sin_addr = dummy; 304 dst.sin_addr = dummy;
314 dst.sin_port = htons (NAT_TRAV_PORT); 305 dst.sin_port = htons (NAT_TRAV_PORT);
315 err = sendto(udpsock, 306 err = sendto (udpsock, NULL, 0, 0, (struct sockaddr *) &dst, sizeof (dst));
316 NULL, 0, 0,
317 (struct sockaddr*)&dst,
318 sizeof(dst));
319 if (err < 0) 307 if (err < 0)
320 { 308 {
321#if VERBOSE 309#if VERBOSE
322 fprintf(stderr, 310 fprintf (stderr, "sendto failed: %s\n", strerror (errno));
323 "sendto failed: %s\n", strerror(errno));
324#endif 311#endif
325 } 312 }
326 else if (0 != err) 313 else if (0 != err)
327 { 314 {
328 fprintf(stderr, 315 fprintf (stderr, "Error: partial send of ICMP message\n");
329 "Error: partial send of ICMP message\n"); 316 }
330 }
331} 317}
332 318
333 319
@@ -349,96 +335,75 @@ process_icmp_response ()
349 335
350 have = read (icmpsock, buf, sizeof (buf)); 336 have = read (icmpsock, buf, sizeof (buf));
351 if (-1 == have) 337 if (-1 == have)
352 { 338 {
353 fprintf (stderr, 339 fprintf (stderr, "Error reading raw socket: %s\n", strerror (errno));
354 "Error reading raw socket: %s\n", 340 return;
355 strerror (errno)); 341 }
356 return;
357 }
358#if VERBOSE 342#if VERBOSE
359 fprintf (stderr, 343 fprintf (stderr, "Received message of %u bytes\n", (unsigned int) have);
360 "Received message of %u bytes\n",
361 (unsigned int) have);
362#endif 344#endif
363 if (have < (ssize_t) (sizeof (struct ip_header) + sizeof (struct icmp_ttl_exceeded_header) + sizeof (struct ip_header))) 345 if (have <
364 { 346 (ssize_t) (sizeof (struct ip_header) +
365 /* malformed */ 347 sizeof (struct icmp_ttl_exceeded_header) +
366 return; 348 sizeof (struct ip_header)))
367 } 349 {
350 /* malformed */
351 return;
352 }
368 off = 0; 353 off = 0;
369 memcpy (&ip_pkt, 354 memcpy (&ip_pkt, &buf[off], sizeof (struct ip_header));
370 &buf[off],
371 sizeof (struct ip_header));
372 off += sizeof (struct ip_header); 355 off += sizeof (struct ip_header);
373 memcpy(&source_ip, 356 memcpy (&source_ip, &ip_pkt.src_ip, sizeof (source_ip));
374 &ip_pkt.src_ip, 357 memcpy (&icmp_ttl, &buf[off], sizeof (struct icmp_ttl_exceeded_header));
375 sizeof (source_ip));
376 memcpy (&icmp_ttl,
377 &buf[off],
378 sizeof (struct icmp_ttl_exceeded_header));
379 off += sizeof (struct icmp_ttl_exceeded_header); 358 off += sizeof (struct icmp_ttl_exceeded_header);
380 if ( (ICMP_TIME_EXCEEDED != icmp_ttl.type) || 359 if ((ICMP_TIME_EXCEEDED != icmp_ttl.type) || (0 != icmp_ttl.code))
381 (0 != icmp_ttl.code) ) 360 {
382 { 361 /* different type than what we want */
383 /* different type than what we want */ 362 return;
384 return; 363 }
385 }
386 /* skip 2nd IP header */ 364 /* skip 2nd IP header */
387 memcpy (&ip_pkt, 365 memcpy (&ip_pkt, &buf[off], sizeof (struct ip_header));
388 &buf[off],
389 sizeof (struct ip_header));
390 off += sizeof (struct ip_header); 366 off += sizeof (struct ip_header);
391 367
392 switch (ip_pkt.proto) 368 switch (ip_pkt.proto)
369 {
370 case IPPROTO_ICMP:
371 if (have != (sizeof (struct ip_header) * 2 +
372 sizeof (struct icmp_ttl_exceeded_header) +
373 sizeof (struct icmp_echo_header)))
393 { 374 {
394 case IPPROTO_ICMP: 375 /* malformed */
395 if (have != (sizeof (struct ip_header) * 2 +
396 sizeof (struct icmp_ttl_exceeded_header) +
397 sizeof (struct icmp_echo_header)) )
398 {
399 /* malformed */
400 return;
401 }
402 /* grab ICMP ECHO content */
403 memcpy (&icmp_echo,
404 &buf[off],
405 sizeof (struct icmp_echo_header));
406 port = (uint16_t) ntohl (icmp_echo.reserved);
407 break;
408 case IPPROTO_UDP:
409 if (have != (sizeof (struct ip_header) * 2 +
410 sizeof (struct icmp_ttl_exceeded_header) +
411 sizeof (struct udp_header)) )
412 {
413 /* malformed */
414 return;
415 }
416 /* grab UDP content */
417 memcpy (&udp_pkt,
418 &buf[off],
419 sizeof (struct udp_header));
420 port = ntohs (udp_pkt.length);
421 break;
422 default:
423 /* different type than what we want */
424 return; 376 return;
425 } 377 }
378 /* grab ICMP ECHO content */
379 memcpy (&icmp_echo, &buf[off], sizeof (struct icmp_echo_header));
380 port = (uint16_t) ntohl (icmp_echo.reserved);
381 break;
382 case IPPROTO_UDP:
383 if (have != (sizeof (struct ip_header) * 2 +
384 sizeof (struct icmp_ttl_exceeded_header) +
385 sizeof (struct udp_header)))
386 {
387 /* malformed */
388 return;
389 }
390 /* grab UDP content */
391 memcpy (&udp_pkt, &buf[off], sizeof (struct udp_header));
392 port = ntohs (udp_pkt.length);
393 break;
394 default:
395 /* different type than what we want */
396 return;
397 }
426 398
427 if (port == 0) 399 if (port == 0)
428 fprintf (stdout, 400 fprintf (stdout,
429 "%s\n", 401 "%s\n", inet_ntop (AF_INET, &source_ip, buf, sizeof (buf)));
430 inet_ntop (AF_INET,
431 &source_ip,
432 buf,
433 sizeof (buf)));
434 else 402 else
435 fprintf (stdout, 403 fprintf (stdout,
436 "%s:%u\n", 404 "%s:%u\n",
437 inet_ntop (AF_INET, 405 inet_ntop (AF_INET,
438 &source_ip, 406 &source_ip, buf, sizeof (buf)), (unsigned int) port);
439 buf,
440 sizeof (buf)),
441 (unsigned int) port);
442 fflush (stdout); 407 fflush (stdout);
443} 408}
444 409
@@ -455,21 +420,18 @@ make_icmp_socket ()
455 420
456 ret = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); 421 ret = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
457 if (-1 == ret) 422 if (-1 == ret)
458 { 423 {
459 fprintf (stderr, 424 fprintf (stderr, "Error opening RAW socket: %s\n", strerror (errno));
460 "Error opening RAW socket: %s\n", 425 return -1;
461 strerror (errno)); 426 }
462 return -1;
463 }
464 if (ret >= FD_SETSIZE) 427 if (ret >= FD_SETSIZE)
465 { 428 {
466 fprintf (stderr, 429 fprintf (stderr,
467 "Socket number too large (%d > %u)\n", 430 "Socket number too large (%d > %u)\n",
468 ret, 431 ret, (unsigned int) FD_SETSIZE);
469 (unsigned int) FD_SETSIZE); 432 close (ret);
470 close (ret); 433 return -1;
471 return -1; 434 }
472 }
473 return ret; 435 return ret;
474} 436}
475 437
@@ -487,34 +449,24 @@ make_raw_socket ()
487 449
488 ret = socket (AF_INET, SOCK_RAW, IPPROTO_RAW); 450 ret = socket (AF_INET, SOCK_RAW, IPPROTO_RAW);
489 if (-1 == ret) 451 if (-1 == ret)
490 { 452 {
491 fprintf (stderr, 453 fprintf (stderr, "Error opening RAW socket: %s\n", strerror (errno));
492 "Error opening RAW socket: %s\n", 454 return -1;
493 strerror (errno)); 455 }
494 return -1; 456 if (-1 == setsockopt (ret,
495 } 457 SOL_SOCKET, SO_BROADCAST, (char *) &one, sizeof (one)))
496 if (-1 == setsockopt(ret, 458 {
497 SOL_SOCKET, 459 fprintf (stderr, "setsockopt failed: %s\n", strerror (errno));
498 SO_BROADCAST, 460 close (ret);
499 (char *)&one, sizeof(one))) 461 return -1;
500 { 462 }
501 fprintf(stderr, 463 if (-1 == setsockopt (ret,
502 "setsockopt failed: %s\n", 464 IPPROTO_IP, IP_HDRINCL, (char *) &one, sizeof (one)))
503 strerror (errno)); 465 {
504 close (ret); 466 fprintf (stderr, "setsockopt failed: %s\n", strerror (errno));
505 return -1; 467 close (ret);
506 } 468 return -1;
507 if (-1 == setsockopt(ret, 469 }
508 IPPROTO_IP,
509 IP_HDRINCL,
510 (char *)&one, sizeof(one)))
511 {
512 fprintf(stderr,
513 "setsockopt failed: %s\n",
514 strerror (errno));
515 close (ret);
516 return -1;
517 }
518 return ret; 470 return ret;
519} 471}
520 472
@@ -533,15 +485,11 @@ make_udp_socket (const struct in_addr *my_ip)
533 485
534 ret = socket (AF_INET, SOCK_DGRAM, 0); 486 ret = socket (AF_INET, SOCK_DGRAM, 0);
535 if (-1 == ret) 487 if (-1 == ret)
536 { 488 {
537 fprintf (stderr, 489 fprintf (stderr, "Error opening UDP socket: %s\n", strerror (errno));
538 "Error opening UDP socket: %s\n", 490 return -1;
539 strerror (errno)); 491 }
540 return -1; 492 memset (&addr, 0, sizeof (addr));
541 }
542 memset (&addr,
543 0,
544 sizeof (addr));
545 addr.sin_family = AF_INET; 493 addr.sin_family = AF_INET;
546#if HAVE_SOCKADDR_IN_SIN_LEN 494#if HAVE_SOCKADDR_IN_SIN_LEN
547 addr.sin_len = sizeof (struct sockaddr_in); 495 addr.sin_len = sizeof (struct sockaddr_in);
@@ -549,23 +497,19 @@ make_udp_socket (const struct in_addr *my_ip)
549 addr.sin_addr = *my_ip; 497 addr.sin_addr = *my_ip;
550 addr.sin_port = htons (NAT_TRAV_PORT); 498 addr.sin_port = htons (NAT_TRAV_PORT);
551 499
552 if (0 != bind (ret, 500 if (0 != bind (ret, &addr, sizeof (addr)))
553 &addr, 501 {
554 sizeof(addr))) 502 fprintf (stderr,
555 { 503 "Error binding UDP socket to port %u: %s\n",
556 fprintf (stderr, 504 NAT_TRAV_PORT, strerror (errno));
557 "Error binding UDP socket to port %u: %s\n", 505 /* likely problematic, but not certain, try to continue */
558 NAT_TRAV_PORT, 506 }
559 strerror (errno));
560 /* likely problematic, but not certain, try to continue */
561 }
562 return ret; 507 return ret;
563} 508}
564 509
565 510
566int 511int
567main (int argc, 512main (int argc, char *const *argv)
568 char *const *argv)
569{ 513{
570 struct in_addr external; 514 struct in_addr external;
571 fd_set rs; 515 fd_set rs;
@@ -574,72 +518,65 @@ main (int argc,
574 unsigned int alt; 518 unsigned int alt;
575 519
576 if (2 != argc) 520 if (2 != argc)
577 { 521 {
578 fprintf (stderr, 522 fprintf (stderr,
579 "This program must be started with our (internal NAT) IP as the only argument.\n"); 523 "This program must be started with our (internal NAT) IP as the only argument.\n");
580 return 1; 524 return 1;
581 } 525 }
582 if (1 != inet_pton (AF_INET, argv[1], &external)) 526 if (1 != inet_pton (AF_INET, argv[1], &external))
583 { 527 {
584 fprintf (stderr, 528 fprintf (stderr, "Error parsing IPv4 address: %s\n", strerror (errno));
585 "Error parsing IPv4 address: %s\n", 529 return 1;
586 strerror (errno)); 530 }
587 return 1;
588 }
589 if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy)) 531 if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy))
590 { 532 {
591 fprintf (stderr, 533 fprintf (stderr, "Internal error converting dummy IP to binary.\n");
592 "Internal error converting dummy IP to binary.\n"); 534 return 2;
593 return 2; 535 }
594 } 536 if (-1 == (icmpsock = make_icmp_socket ()))
595 if (-1 == (icmpsock = make_icmp_socket())) 537 {
596 { 538 return 3;
597 return 3; 539 }
598 } 540 if (-1 == (rawsock = make_raw_socket ()))
599 if (-1 == (rawsock = make_raw_socket())) 541 {
600 { 542 close (icmpsock);
601 close (icmpsock); 543 return 3;
602 return 3; 544 }
603 }
604 uid = getuid (); 545 uid = getuid ();
605 if (0 != setresuid (uid, uid, uid)) 546 if (0 != setresuid (uid, uid, uid))
606 { 547 {
607 fprintf (stderr, 548 fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno));
608 "Failed to setresuid: %s\n", 549 /* not critical, continue anyway */
609 strerror (errno)); 550 }
610 /* not critical, continue anyway */ 551 if (-1 == (udpsock = make_udp_socket (&external)))
611 } 552 {
612 if (-1 == (udpsock = make_udp_socket(&external))) 553 close (icmpsock);
613 { 554 close (rawsock);
614 close (icmpsock); 555 return 3;
615 close (rawsock); 556 }
616 return 3;
617 }
618 alt = 0; 557 alt = 0;
619 while (1) 558 while (1)
559 {
560 FD_ZERO (&rs);
561 FD_SET (icmpsock, &rs);
562 tv.tv_sec = 0;
563 tv.tv_usec = ICMP_SEND_FREQUENCY_MS * 1000;
564 if (-1 == select (icmpsock + 1, &rs, NULL, NULL, &tv))
620 { 565 {
621 FD_ZERO (&rs); 566 if (errno == EINTR)
622 FD_SET (icmpsock, &rs); 567 continue;
623 tv.tv_sec = 0; 568 fprintf (stderr, "select failed: %s\n", strerror (errno));
624 tv.tv_usec = ICMP_SEND_FREQUENCY_MS * 1000; 569 break;
625 if (-1 == select (icmpsock + 1, &rs, NULL, NULL, &tv))
626 {
627 if (errno == EINTR)
628 continue;
629 fprintf (stderr,
630 "select failed: %s\n",
631 strerror (errno));
632 break;
633 }
634 if (1 == getppid()) /* Check the parent process id, if 1 the parent has died, so we should die too */
635 break;
636 if (FD_ISSET (icmpsock, &rs))
637 process_icmp_response ();
638 if (0 == (++alt % 2))
639 send_icmp_echo (&external);
640 else
641 send_udp ();
642 } 570 }
571 if (1 == getppid ()) /* Check the parent process id, if 1 the parent has died, so we should die too */
572 break;
573 if (FD_ISSET (icmpsock, &rs))
574 process_icmp_response ();
575 if (0 == (++alt % 2))
576 send_icmp_echo (&external);
577 else
578 send_udp ();
579 }
643 /* select failed (internal error or OS out of resources) */ 580 /* select failed (internal error or OS out of resources) */
644 close (icmpsock); 581 close (icmpsock);
645 close (rawsock); 582 close (rawsock);