summaryrefslogtreecommitdiff
path: root/src/nat/gnunet-service-nat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nat/gnunet-service-nat.c')
-rw-r--r--src/nat/gnunet-service-nat.c2190
1 files changed, 1100 insertions, 1090 deletions
diff --git a/src/nat/gnunet-service-nat.c b/src/nat/gnunet-service-nat.c
index 2498a990a..6fd09a7d9 100644
--- a/src/nat/gnunet-service-nat.c
+++ b/src/nat/gnunet-service-nat.c
@@ -1,19 +1,19 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2016, 2017 GNUnet e.V. 3 Copyright (C) 2016, 2017 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License, 7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version. 8 or (at your option) any later version.
9 9
10 GNUnet is distributed in the hope that it will be useful, but 10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of 11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details. 13 Affero General Public License for more details.
14 14
15 You should have received a copy of the GNU Affero General Public License 15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 17
18 SPDX-License-Identifier: AGPL3.0-or-later 18 SPDX-License-Identifier: AGPL3.0-or-later
19 */ 19 */
@@ -55,24 +55,23 @@
55 * How often should we ask the OS about a list of active 55 * How often should we ask the OS about a list of active
56 * network interfaces? 56 * network interfaces?
57 */ 57 */
58#define SCAN_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) 58#define SCAN_FREQ GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 15)
59 59
60/** 60/**
61 * How long do we wait until we forcefully terminate autoconfiguration? 61 * How long do we wait until we forcefully terminate autoconfiguration?
62 */ 62 */
63#define AUTOCONFIG_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) 63#define AUTOCONFIG_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5)
64 64
65/** 65/**
66 * How often do we scan for changes in how our external (dyndns) hostname resolves? 66 * How often do we scan for changes in how our external (dyndns) hostname resolves?
67 */ 67 */
68#define DYNDNS_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 7) 68#define DYNDNS_FREQUENCY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 7)
69 69
70 70
71/** 71/**
72 * Information we track per client address. 72 * Information we track per client address.
73 */ 73 */
74struct ClientAddress 74struct ClientAddress {
75{
76 /** 75 /**
77 * Network address used by the client. 76 * Network address used by the client.
78 */ 77 */
@@ -84,15 +83,13 @@ struct ClientAddress
84 * pending. 83 * pending.
85 */ 84 */
86 struct GNUNET_NAT_MiniHandle *mh; 85 struct GNUNET_NAT_MiniHandle *mh;
87
88}; 86};
89 87
90 88
91/** 89/**
92 * List of local addresses this system has. 90 * List of local addresses this system has.
93 */ 91 */
94struct LocalAddressList 92struct LocalAddressList {
95{
96 /** 93 /**
97 * This is a linked list. 94 * This is a linked list.
98 */ 95 */
@@ -131,16 +128,13 @@ struct LocalAddressList
131 * What type of address is this? 128 * What type of address is this?
132 */ 129 */
133 enum GNUNET_NAT_AddressClass ac; 130 enum GNUNET_NAT_AddressClass ac;
134
135}; 131};
136 132
137 133
138/** 134/**
139 * Internal data structure we track for each of our clients. 135 * Internal data structure we track for each of our clients.
140 */ 136 */
141struct ClientHandle 137struct ClientHandle {
142{
143
144 /** 138 /**
145 * Kept in a DLL. 139 * Kept in a DLL.
146 */ 140 */
@@ -232,15 +226,13 @@ struct ClientHandle
232 * Client's IPPROTO, e.g. IPPROTO_UDP or IPPROTO_TCP. 226 * Client's IPPROTO, e.g. IPPROTO_UDP or IPPROTO_TCP.
233 */ 227 */
234 uint8_t proto; 228 uint8_t proto;
235
236}; 229};
237 230
238 231
239/** 232/**
240 * External IP address as given to us via some STUN server. 233 * External IP address as given to us via some STUN server.
241 */ 234 */
242struct StunExternalIP 235struct StunExternalIP {
243{
244 /** 236 /**
245 * Kept in a DLL. 237 * Kept in a DLL.
246 */ 238 */
@@ -344,22 +336,22 @@ int enable_upnp;
344 * @param lal entry to free 336 * @param lal entry to free
345 */ 337 */
346static void 338static void
347free_lal (struct LocalAddressList *lal) 339free_lal(struct LocalAddressList *lal)
348{ 340{
349 GNUNET_CONTAINER_DLL_remove (lal_head, 341 GNUNET_CONTAINER_DLL_remove(lal_head,
350 lal_tail, 342 lal_tail,
351 lal); 343 lal);
352 if (NULL != lal->hc) 344 if (NULL != lal->hc)
353 { 345 {
354 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, 346 GNUNET_log(GNUNET_ERROR_TYPE_MESSAGE,
355 "Lost NATed local address %s, stopping NAT server\n", 347 "Lost NATed local address %s, stopping NAT server\n",
356 GNUNET_a2s ((const struct sockaddr *) &lal->addr, 348 GNUNET_a2s((const struct sockaddr *)&lal->addr,
357 sizeof (struct sockaddr_in))); 349 sizeof(struct sockaddr_in)));
358 350
359 GN_stop_gnunet_nat_server_ (lal->hc); 351 GN_stop_gnunet_nat_server_(lal->hc);
360 lal->hc = NULL; 352 lal->hc = NULL;
361 } 353 }
362 GNUNET_free (lal); 354 GNUNET_free(lal);
363} 355}
364 356
365 357
@@ -367,12 +359,12 @@ free_lal (struct LocalAddressList *lal)
367 * Free the DLL starting at #lal_head. 359 * Free the DLL starting at #lal_head.
368 */ 360 */
369static void 361static void
370destroy_lal () 362destroy_lal()
371{ 363{
372 struct LocalAddressList *lal; 364 struct LocalAddressList *lal;
373 365
374 while (NULL != (lal = lal_head)) 366 while (NULL != (lal = lal_head))
375 free_lal (lal); 367 free_lal(lal);
376} 368}
377 369
378 370
@@ -385,53 +377,55 @@ destroy_lal ()
385 * @return #GNUNET_OK if message is well-formed 377 * @return #GNUNET_OK if message is well-formed
386 */ 378 */
387static int 379static int
388check_register (void *cls, 380check_register(void *cls,
389 const struct GNUNET_NAT_RegisterMessage *message) 381 const struct GNUNET_NAT_RegisterMessage *message)
390{ 382{
391 uint16_t num_addrs = ntohs (message->num_addrs); 383 uint16_t num_addrs = ntohs(message->num_addrs);
392 const char *off = (const char *) &message[1]; 384 const char *off = (const char *)&message[1];
393 size_t left = ntohs (message->header.size) - sizeof (*message); 385 size_t left = ntohs(message->header.size) - sizeof(*message);
394
395 for (unsigned int i=0;i<num_addrs;i++)
396 {
397 size_t alen;
398 const struct sockaddr *sa = (const struct sockaddr *) off;
399 386
400 if (sizeof (sa_family_t) > left) 387 for (unsigned int i = 0; i < num_addrs; i++)
401 { 388 {
402 GNUNET_break (0); 389 size_t alen;
403 return GNUNET_SYSERR; 390 const struct sockaddr *sa = (const struct sockaddr *)off;
404 } 391
405 switch (sa->sa_family) 392 if (sizeof(sa_family_t) > left)
406 { 393 {
407 case AF_INET: 394 GNUNET_break(0);
408 alen = sizeof (struct sockaddr_in); 395 return GNUNET_SYSERR;
409 break; 396 }
410 case AF_INET6: 397 switch (sa->sa_family)
411 alen = sizeof (struct sockaddr_in6); 398 {
412 break; 399 case AF_INET:
400 alen = sizeof(struct sockaddr_in);
401 break;
402
403 case AF_INET6:
404 alen = sizeof(struct sockaddr_in6);
405 break;
406
413#if AF_UNIX 407#if AF_UNIX
414 case AF_UNIX: 408 case AF_UNIX:
415 alen = sizeof (struct sockaddr_un); 409 alen = sizeof(struct sockaddr_un);
416 break; 410 break;
417#endif 411#endif
418 default: 412 default:
419 GNUNET_break (0); 413 GNUNET_break(0);
420 return GNUNET_SYSERR; 414 return GNUNET_SYSERR;
415 }
416 if (alen > left)
417 {
418 GNUNET_break(0);
419 return GNUNET_SYSERR;
420 }
421 off += alen;
422 left -= alen;
421 } 423 }
422 if (alen > left) 424 if (left != ntohs(message->str_len))
423 { 425 {
424 GNUNET_break (0); 426 GNUNET_break(0);
425 return GNUNET_SYSERR; 427 return GNUNET_SYSERR;
426 } 428 }
427 off += alen;
428 left -= alen;
429 }
430 if (left != ntohs (message->str_len))
431 {
432 GNUNET_break (0);
433 return GNUNET_SYSERR;
434 }
435 return GNUNET_OK; 429 return GNUNET_OK;
436} 430}
437 431
@@ -445,9 +439,9 @@ check_register (void *cls,
445 * @return #GNUNET_YES if @a ip is in @a network 439 * @return #GNUNET_YES if @a ip is in @a network
446 */ 440 */
447static int 441static int
448match_ipv4 (const char *network, 442match_ipv4(const char *network,
449 const struct in_addr *ip, 443 const struct in_addr *ip,
450 uint8_t bits) 444 uint8_t bits)
451{ 445{
452 struct in_addr net; 446 struct in_addr net;
453 447
@@ -455,10 +449,10 @@ match_ipv4 (const char *network,
455 return GNUNET_YES; 449 return GNUNET_YES;
456 if (0 == bits) 450 if (0 == bits)
457 return GNUNET_YES; 451 return GNUNET_YES;
458 GNUNET_assert (1 == inet_pton (AF_INET, 452 GNUNET_assert(1 == inet_pton(AF_INET,
459 network, 453 network,
460 &net)); 454 &net));
461 return ! ((ip->s_addr ^ net.s_addr) & htonl (0xFFFFFFFFu << (32 - bits))); 455 return !((ip->s_addr ^ net.s_addr) & htonl(0xFFFFFFFFu << (32 - bits)));
462} 456}
463 457
464 458
@@ -471,9 +465,9 @@ match_ipv4 (const char *network,
471 * @return #GNUNET_YES if @a ip is in @a network 465 * @return #GNUNET_YES if @a ip is in @a network
472 */ 466 */
473static int 467static int
474match_ipv6 (const char *network, 468match_ipv6(const char *network,
475 const struct in6_addr *ip, 469 const struct in6_addr *ip,
476 uint8_t bits) 470 uint8_t bits)
477{ 471{
478 struct in6_addr net; 472 struct in6_addr net;
479 struct in6_addr mask; 473 struct in6_addr mask;
@@ -481,27 +475,27 @@ match_ipv6 (const char *network,
481 475
482 if (0 == bits) 476 if (0 == bits)
483 return GNUNET_YES; 477 return GNUNET_YES;
484 GNUNET_assert (1 == inet_pton (AF_INET6, 478 GNUNET_assert(1 == inet_pton(AF_INET6,
485 network, 479 network,
486 &net)); 480 &net));
487 memset (&mask, 0, sizeof (mask)); 481 memset(&mask, 0, sizeof(mask));
488 if (0 == GNUNET_memcmp (&mask, 482 if (0 == GNUNET_memcmp(&mask,
489 ip)) 483 ip))
490 return GNUNET_YES; 484 return GNUNET_YES;
491 off = 0; 485 off = 0;
492 while (bits > 8) 486 while (bits > 8)
493 { 487 {
494 mask.s6_addr[off++] = 0xFF; 488 mask.s6_addr[off++] = 0xFF;
495 bits -= 8; 489 bits -= 8;
496 } 490 }
497 while (bits > 0) 491 while (bits > 0)
498 { 492 {
499 mask.s6_addr[off] = (mask.s6_addr[off] >> 1) + 0x80; 493 mask.s6_addr[off] = (mask.s6_addr[off] >> 1) + 0x80;
500 bits--; 494 bits--;
501 } 495 }
502 for (unsigned j = 0; j < sizeof (struct in6_addr) / sizeof (uint32_t); j++) 496 for (unsigned j = 0; j < sizeof(struct in6_addr) / sizeof(uint32_t); j++)
503 if (((((uint32_t *) ip)[j] & ((uint32_t *) &mask)[j])) != 497 if (((((uint32_t *)ip)[j] & ((uint32_t *)&mask)[j])) !=
504 (((uint32_t *) &net)[j] & ((int *) &mask)[j])) 498 (((uint32_t *)&net)[j] & ((int *)&mask)[j]))
505 return GNUNET_NO; 499 return GNUNET_NO;
506 return GNUNET_YES; 500 return GNUNET_YES;
507} 501}
@@ -515,14 +509,14 @@ match_ipv6 (const char *network,
515 * @return #GNUNET_YES if @a ip is in a NAT range 509 * @return #GNUNET_YES if @a ip is in a NAT range
516 */ 510 */
517static int 511static int
518is_nat_v4 (const struct in_addr *ip) 512is_nat_v4(const struct in_addr *ip)
519{ 513{
520 return 514 return
521 match_ipv4 ("10.0.0.0", ip, 8) || /* RFC 1918 */ 515 match_ipv4("10.0.0.0", ip, 8) || /* RFC 1918 */
522 match_ipv4 ("100.64.0.0", ip, 10) || /* CG-NAT, RFC 6598 */ 516 match_ipv4("100.64.0.0", ip, 10) || /* CG-NAT, RFC 6598 */
523 match_ipv4 ("192.168.0.0", ip, 12) || /* RFC 1918 */ 517 match_ipv4("192.168.0.0", ip, 12) || /* RFC 1918 */
524 match_ipv4 ("169.254.0.0", ip, 16) || /* AUTO, RFC 3927 */ 518 match_ipv4("169.254.0.0", ip, 16) || /* AUTO, RFC 3927 */
525 match_ipv4 ("172.16.0.0", ip, 16); /* RFC 1918 */ 519 match_ipv4("172.16.0.0", ip, 16); /* RFC 1918 */
526} 520}
527 521
528 522
@@ -534,21 +528,19 @@ is_nat_v4 (const struct in_addr *ip)
534 * @return #GNUNET_YES if @a ip is in a NAT range 528 * @return #GNUNET_YES if @a ip is in a NAT range
535 */ 529 */
536static int 530static int
537is_nat_v6 (const struct in6_addr *ip) 531is_nat_v6(const struct in6_addr *ip)
538{ 532{
539 return 533 return
540 match_ipv6 ("fc00::", ip, 7) || /* RFC 4193 */ 534 match_ipv6("fc00::", ip, 7) || /* RFC 4193 */
541 match_ipv6 ("fec0::", ip, 10) || /* RFC 3879 */ 535 match_ipv6("fec0::", ip, 10) || /* RFC 3879 */
542 match_ipv6 ("fe80::", ip, 10); /* RFC 4291, link-local */ 536 match_ipv6("fe80::", ip, 10); /* RFC 4291, link-local */
543} 537}
544 538
545 539
546/** 540/**
547 * Closure for #ifc_proc. 541 * Closure for #ifc_proc.
548 */ 542 */
549struct IfcProcContext 543struct IfcProcContext {
550{
551
552 /** 544 /**
553 * Head of DLL of local addresses. 545 * Head of DLL of local addresses.
554 */ 546 */
@@ -558,7 +550,6 @@ struct IfcProcContext
558 * Tail of DLL of local addresses. 550 * Tail of DLL of local addresses.
559 */ 551 */
560 struct LocalAddressList *lal_tail; 552 struct LocalAddressList *lal_tail;
561
562}; 553};
563 554
564 555
@@ -576,13 +567,13 @@ struct IfcProcContext
576 * @return #GNUNET_OK to continue iteration, #GNUNET_SYSERR to abort 567 * @return #GNUNET_OK to continue iteration, #GNUNET_SYSERR to abort
577 */ 568 */
578static int 569static int
579ifc_proc (void *cls, 570ifc_proc(void *cls,
580 const char *name, 571 const char *name,
581 int isDefault, 572 int isDefault,
582 const struct sockaddr *addr, 573 const struct sockaddr *addr,
583 const struct sockaddr *broadcast_addr, 574 const struct sockaddr *broadcast_addr,
584 const struct sockaddr *netmask, 575 const struct sockaddr *netmask,
585 socklen_t addrlen) 576 socklen_t addrlen)
586{ 577{
587 struct IfcProcContext *ifc_ctx = cls; 578 struct IfcProcContext *ifc_ctx = cls;
588 struct LocalAddressList *lal; 579 struct LocalAddressList *lal;
@@ -592,51 +583,53 @@ ifc_proc (void *cls,
592 enum GNUNET_NAT_AddressClass ac; 583 enum GNUNET_NAT_AddressClass ac;
593 584
594 switch (addr->sa_family) 585 switch (addr->sa_family)
595 {
596 case AF_INET:
597 alen = sizeof (struct sockaddr_in);
598 ip4 = &((const struct sockaddr_in *) addr)->sin_addr;
599 if (match_ipv4 ("127.0.0.0", ip4, 8))
600 ac = GNUNET_NAT_AC_LOOPBACK;
601 else if (is_nat_v4 (ip4))
602 ac = GNUNET_NAT_AC_LAN;
603 else
604 ac = GNUNET_NAT_AC_GLOBAL;
605 break;
606 case AF_INET6:
607 alen = sizeof (struct sockaddr_in6);
608 ip6 = &((const struct sockaddr_in6 *) addr)->sin6_addr;
609 if (match_ipv6 ("::1", ip6, 128))
610 ac = GNUNET_NAT_AC_LOOPBACK;
611 else if (is_nat_v6 (ip6))
612 ac = GNUNET_NAT_AC_LAN;
613 else
614 ac = GNUNET_NAT_AC_GLOBAL;
615 if ( (ip6->s6_addr[11] == 0xFF) &&
616 (ip6->s6_addr[12] == 0xFE) )
617 { 586 {
618 /* contains a MAC, be extra careful! */ 587 case AF_INET:
619 ac |= GNUNET_NAT_AC_PRIVATE; 588 alen = sizeof(struct sockaddr_in);
620 } 589 ip4 = &((const struct sockaddr_in *)addr)->sin_addr;
621 break; 590 if (match_ipv4("127.0.0.0", ip4, 8))
591 ac = GNUNET_NAT_AC_LOOPBACK;
592 else if (is_nat_v4(ip4))
593 ac = GNUNET_NAT_AC_LAN;
594 else
595 ac = GNUNET_NAT_AC_GLOBAL;
596 break;
597
598 case AF_INET6:
599 alen = sizeof(struct sockaddr_in6);
600 ip6 = &((const struct sockaddr_in6 *)addr)->sin6_addr;
601 if (match_ipv6("::1", ip6, 128))
602 ac = GNUNET_NAT_AC_LOOPBACK;
603 else if (is_nat_v6(ip6))
604 ac = GNUNET_NAT_AC_LAN;
605 else
606 ac = GNUNET_NAT_AC_GLOBAL;
607 if ((ip6->s6_addr[11] == 0xFF) &&
608 (ip6->s6_addr[12] == 0xFE))
609 {
610 /* contains a MAC, be extra careful! */
611 ac |= GNUNET_NAT_AC_PRIVATE;
612 }
613 break;
614
622#if AF_UNIX 615#if AF_UNIX
623 case AF_UNIX: 616 case AF_UNIX:
624 GNUNET_break (0); 617 GNUNET_break(0);
625 return GNUNET_OK; 618 return GNUNET_OK;
626#endif 619#endif
627 default: 620 default:
628 GNUNET_break (0); 621 GNUNET_break(0);
629 return GNUNET_OK; 622 return GNUNET_OK;
630 } 623 }
631 lal = GNUNET_malloc (sizeof (*lal)); 624 lal = GNUNET_malloc(sizeof(*lal));
632 lal->af = addr->sa_family; 625 lal->af = addr->sa_family;
633 lal->ac = ac; 626 lal->ac = ac;
634 GNUNET_memcpy (&lal->addr, 627 GNUNET_memcpy(&lal->addr,
635 addr, 628 addr,
636 alen); 629 alen);
637 GNUNET_CONTAINER_DLL_insert (ifc_ctx->lal_head, 630 GNUNET_CONTAINER_DLL_insert(ifc_ctx->lal_head,
638 ifc_ctx->lal_tail, 631 ifc_ctx->lal_tail,
639 lal); 632 lal);
640 return GNUNET_OK; 633 return GNUNET_OK;
641} 634}
642 635
@@ -652,30 +645,30 @@ ifc_proc (void *cls,
652 * @param addr_len number of bytes in @a addr 645 * @param addr_len number of bytes in @a addr
653 */ 646 */
654static void 647static void
655notify_client (enum GNUNET_NAT_AddressClass ac, 648notify_client(enum GNUNET_NAT_AddressClass ac,
656 struct ClientHandle *ch, 649 struct ClientHandle *ch,
657 int add, 650 int add,
658 const void *addr, 651 const void *addr,
659 size_t addr_len) 652 size_t addr_len)
660{ 653{
661 struct GNUNET_MQ_Envelope *env; 654 struct GNUNET_MQ_Envelope *env;
662 struct GNUNET_NAT_AddressChangeNotificationMessage *msg; 655 struct GNUNET_NAT_AddressChangeNotificationMessage *msg;
663 656
664 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 657 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
665 "Notifying client about %s of IP %s\n", 658 "Notifying client about %s of IP %s\n",
666 add ? "addition" : "removal", 659 add ? "addition" : "removal",
667 GNUNET_a2s (addr, 660 GNUNET_a2s(addr,
668 addr_len)); 661 addr_len));
669 env = GNUNET_MQ_msg_extra (msg, 662 env = GNUNET_MQ_msg_extra(msg,
670 addr_len, 663 addr_len,
671 GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE); 664 GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE);
672 msg->add_remove = htonl (add); 665 msg->add_remove = htonl(add);
673 msg->addr_class = htonl (ac); 666 msg->addr_class = htonl(ac);
674 GNUNET_memcpy (&msg[1], 667 GNUNET_memcpy(&msg[1],
675 addr, 668 addr,
676 addr_len); 669 addr_len);
677 GNUNET_MQ_send (ch->mq, 670 GNUNET_MQ_send(ch->mq,
678 env); 671 env);
679} 672}
680 673
681 674
@@ -688,121 +681,123 @@ notify_client (enum GNUNET_NAT_AddressClass ac,
688 * @param add #GNUNET_YES to add, #GNUNET_NO to remove 681 * @param add #GNUNET_YES to add, #GNUNET_NO to remove
689 */ 682 */
690static void 683static void
691check_notify_client (struct LocalAddressList *delta, 684check_notify_client(struct LocalAddressList *delta,
692 struct ClientHandle *ch, 685 struct ClientHandle *ch,
693 int add) 686 int add)
694{ 687{
695 size_t alen; 688 size_t alen;
696 struct sockaddr_in v4; 689 struct sockaddr_in v4;
697 struct sockaddr_in6 v6; 690 struct sockaddr_in6 v6;
698 691
699 if (0 == (ch->flags & GNUNET_NAT_RF_ADDRESSES)) 692 if (0 == (ch->flags & GNUNET_NAT_RF_ADDRESSES))
700 {
701 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
702 "Not notifying client as it does not care about addresses\n");
703 return;
704 }
705 switch (delta->af)
706 {
707 case AF_INET:
708 alen = sizeof (struct sockaddr_in);
709 GNUNET_memcpy (&v4,
710 &delta->addr,
711 alen);
712
713 /* Check for client notifications */
714 for (unsigned int i=0;i<ch->num_caddrs;i++)
715 { 693 {
716 const struct sockaddr_in *c4; 694 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
717 695 "Not notifying client as it does not care about addresses\n");
718 if (AF_INET != ch->caddrs[i].ss.ss_family) 696 return;
719 continue; /* IPv4 not relevant */
720 c4 = (const struct sockaddr_in *) &ch->caddrs[i].ss;
721 if ( match_ipv4 ("127.0.0.1", &c4->sin_addr, 8) &&
722 (0 != c4->sin_addr.s_addr) &&
723 (! match_ipv4 ("127.0.0.1", &v4.sin_addr, 8)) )
724 continue; /* bound to loopback, but this is not loopback */
725 if ( (! match_ipv4 ("127.0.0.1", &c4->sin_addr, 8) ) &&
726 match_ipv4 ("127.0.0.1", &v4.sin_addr, 8) )
727 continue; /* bound to non-loopback, but this is loopback */
728 if ( (0 != (delta->ac & GNUNET_NAT_AC_EXTERN)) &&
729 (0 != c4->sin_addr.s_addr) &&
730 (! is_nat_v4 (&v4.sin_addr)) )
731 continue; /* based on external-IP, but this IP is not
732 from private address range. */
733 if ( (0 != GNUNET_memcmp (&v4.sin_addr,
734 &c4->sin_addr)) &&
735 (0 != c4->sin_addr.s_addr) &&
736 (! is_nat_v4 (&c4->sin_addr)) )
737 continue; /* this IP is not from private address range,
738 and IP does not match. */
739
740 /* OK, IP seems relevant, notify client */
741 if (0 == htons (v4.sin_port))
742 v4.sin_port = c4->sin_port;
743 notify_client (delta->ac,
744 ch,
745 add,
746 &v4,
747 alen);
748 } 697 }
749 break; 698 switch (delta->af)
750 case AF_INET6:
751 alen = sizeof (struct sockaddr_in6);
752 GNUNET_memcpy (&v6,
753 &delta->addr,
754 alen);
755 for (unsigned int i=0;i<ch->num_caddrs;i++)
756 { 699 {
757 const struct sockaddr_in6 *c6; 700 case AF_INET:
758 701 alen = sizeof(struct sockaddr_in);
759 if (AF_INET6 != ch->caddrs[i].ss.ss_family) 702 GNUNET_memcpy(&v4,
760 continue; /* IPv4 not relevant */ 703 &delta->addr,
761 c6 = (const struct sockaddr_in6 *) &ch->caddrs[i].ss; 704 alen);
762 if ( match_ipv6 ("::1", &c6->sin6_addr, 128) && 705
763 (0 != GNUNET_memcmp (&c6->sin6_addr, 706 /* Check for client notifications */
764 &in6addr_any)) && 707 for (unsigned int i = 0; i < ch->num_caddrs; i++)
765 (! match_ipv6 ("::1", &v6.sin6_addr, 128)) ) 708 {
766 continue; /* bound to loopback, but this is not loopback */ 709 const struct sockaddr_in *c4;
767 if ( (! match_ipv6 ("::1", &c6->sin6_addr, 128) ) && 710
768 match_ipv6 ("::1", &v6.sin6_addr, 128) ) 711 if (AF_INET != ch->caddrs[i].ss.ss_family)
769 continue; /* bound to non-loopback, but this is loopback */ 712 continue; /* IPv4 not relevant */
770 if ( (0 != (delta->ac & GNUNET_NAT_AC_EXTERN)) && 713 c4 = (const struct sockaddr_in *)&ch->caddrs[i].ss;
771 (0 != GNUNET_memcmp (&c6->sin6_addr, 714 if (match_ipv4("127.0.0.1", &c4->sin_addr, 8) &&
772 &in6addr_any)) && 715 (0 != c4->sin_addr.s_addr) &&
773 (! is_nat_v6 (&v6.sin6_addr)) ) 716 (!match_ipv4("127.0.0.1", &v4.sin_addr, 8)))
774 continue; /* based on external-IP, but this IP is not 717 continue; /* bound to loopback, but this is not loopback */
775 from private address range. */ 718 if ((!match_ipv4("127.0.0.1", &c4->sin_addr, 8)) &&
776 if ( (0 != GNUNET_memcmp (&v6.sin6_addr, 719 match_ipv4("127.0.0.1", &v4.sin_addr, 8))
777 &c6->sin6_addr)) && 720 continue; /* bound to non-loopback, but this is loopback */
778 (0 != GNUNET_memcmp (&c6->sin6_addr, 721 if ((0 != (delta->ac & GNUNET_NAT_AC_EXTERN)) &&
779 &in6addr_any)) && 722 (0 != c4->sin_addr.s_addr) &&
780 (! is_nat_v6 (&c6->sin6_addr)) ) 723 (!is_nat_v4(&v4.sin_addr)))
781 continue; /* this IP is not from private address range, 724 continue; /* based on external-IP, but this IP is not
782 and IP does not match. */ 725 from private address range. */
783 if ( (match_ipv6 ("fe80::", &c6->sin6_addr, 10)) && 726 if ((0 != GNUNET_memcmp(&v4.sin_addr,
784 (0 != GNUNET_memcmp (&c6->sin6_addr, 727 &c4->sin_addr)) &&
785 &in6addr_any)) && 728 (0 != c4->sin_addr.s_addr) &&
786 (0 != GNUNET_memcmp (&v6.sin6_addr, 729 (!is_nat_v4(&c4->sin_addr)))
787 &c6->sin6_addr)) && 730 continue; /* this IP is not from private address range,
788 (0 == (delta->ac & GNUNET_NAT_AC_EXTERN)) ) 731 and IP does not match. */
789 continue; /* client bound to link-local, and the other address 732
790 does not match and is not an external IP */ 733 /* OK, IP seems relevant, notify client */
791 734 if (0 == htons(v4.sin_port))
792 /* OK, IP seems relevant, notify client */ 735 v4.sin_port = c4->sin_port;
793 if (0 == htons (v6.sin6_port)) 736 notify_client(delta->ac,
794 v6.sin6_port = c6->sin6_port; 737 ch,
795 notify_client (delta->ac, 738 add,
796 ch, 739 &v4,
797 add, 740 alen);
798 &v6, 741 }
799 alen); 742 break;
743
744 case AF_INET6:
745 alen = sizeof(struct sockaddr_in6);
746 GNUNET_memcpy(&v6,
747 &delta->addr,
748 alen);
749 for (unsigned int i = 0; i < ch->num_caddrs; i++)
750 {
751 const struct sockaddr_in6 *c6;
752
753 if (AF_INET6 != ch->caddrs[i].ss.ss_family)
754 continue; /* IPv4 not relevant */
755 c6 = (const struct sockaddr_in6 *)&ch->caddrs[i].ss;
756 if (match_ipv6("::1", &c6->sin6_addr, 128) &&
757 (0 != GNUNET_memcmp(&c6->sin6_addr,
758 &in6addr_any)) &&
759 (!match_ipv6("::1", &v6.sin6_addr, 128)))
760 continue; /* bound to loopback, but this is not loopback */
761 if ((!match_ipv6("::1", &c6->sin6_addr, 128)) &&
762 match_ipv6("::1", &v6.sin6_addr, 128))
763 continue; /* bound to non-loopback, but this is loopback */
764 if ((0 != (delta->ac & GNUNET_NAT_AC_EXTERN)) &&
765 (0 != GNUNET_memcmp(&c6->sin6_addr,
766 &in6addr_any)) &&
767 (!is_nat_v6(&v6.sin6_addr)))
768 continue; /* based on external-IP, but this IP is not
769 from private address range. */
770 if ((0 != GNUNET_memcmp(&v6.sin6_addr,
771 &c6->sin6_addr)) &&
772 (0 != GNUNET_memcmp(&c6->sin6_addr,
773 &in6addr_any)) &&
774 (!is_nat_v6(&c6->sin6_addr)))
775 continue; /* this IP is not from private address range,
776 and IP does not match. */
777 if ((match_ipv6("fe80::", &c6->sin6_addr, 10)) &&
778 (0 != GNUNET_memcmp(&c6->sin6_addr,
779 &in6addr_any)) &&
780 (0 != GNUNET_memcmp(&v6.sin6_addr,
781 &c6->sin6_addr)) &&
782 (0 == (delta->ac & GNUNET_NAT_AC_EXTERN)))
783 continue; /* client bound to link-local, and the other address
784 does not match and is not an external IP */
785
786 /* OK, IP seems relevant, notify client */
787 if (0 == htons(v6.sin6_port))
788 v6.sin6_port = c6->sin6_port;
789 notify_client(delta->ac,
790 ch,
791 add,
792 &v6,
793 alen);
794 }
795 break;
796
797 default:
798 GNUNET_break(0);
799 return;
800 } 800 }
801 break;
802 default:
803 GNUNET_break (0);
804 return;
805 }
806} 801}
807 802
808 803
@@ -814,15 +809,15 @@ check_notify_client (struct LocalAddressList *delta,
814 * @param add #GNUNET_YES to add, #GNUNET_NO to remove 809 * @param add #GNUNET_YES to add, #GNUNET_NO to remove
815 */ 810 */
816static void 811static void
817notify_clients (struct LocalAddressList *delta, 812notify_clients(struct LocalAddressList *delta,
818 int add) 813 int add)
819{ 814{
820 for (struct ClientHandle *ch = ch_head; 815 for (struct ClientHandle *ch = ch_head;
821 NULL != ch; 816 NULL != ch;
822 ch = ch->next) 817 ch = ch->next)
823 check_notify_client (delta, 818 check_notify_client(delta,
824 ch, 819 ch,
825 add); 820 add);
826} 821}
827 822
828 823
@@ -835,74 +830,74 @@ notify_clients (struct LocalAddressList *delta,
835 * @param add #GNUNET_YES to add, #GNUNET_NO to remove 830 * @param add #GNUNET_YES to add, #GNUNET_NO to remove
836 */ 831 */
837static void 832static void
838notify_client_external_ipv4_change (void *cls, 833notify_client_external_ipv4_change(void *cls,
839 const struct in_addr *v4, 834 const struct in_addr *v4,
840 int add) 835 int add)
841{ 836{
842 struct ClientHandle *ch = cls; 837 struct ClientHandle *ch = cls;
843 struct sockaddr_in sa; 838 struct sockaddr_in sa;
844 int have_v4; 839 int have_v4;
845 840
846 /* (0) check if this impacts 'hole_external' */ 841 /* (0) check if this impacts 'hole_external' */
847 if ( (NULL != ch->hole_external) && 842 if ((NULL != ch->hole_external) &&
848 (0 == strcasecmp (ch->hole_external, 843 (0 == strcasecmp(ch->hole_external,
849 "AUTO")) ) 844 "AUTO")))
850 { 845 {
851 struct LocalAddressList lal; 846 struct LocalAddressList lal;
852 struct sockaddr_in *s4; 847 struct sockaddr_in *s4;
853 848
854 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 849 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
855 "Detected eternal IP, can now back-fill AUTO:%u in hole punching specification of `%s'\n", 850 "Detected eternal IP, can now back-fill AUTO:%u in hole punching specification of `%s'\n",
856 (unsigned int) ch->ext_dns_port, 851 (unsigned int)ch->ext_dns_port,
857 ch->section_name); 852 ch->section_name);
858 memset (&lal, 0, sizeof (lal)); 853 memset(&lal, 0, sizeof(lal));
859 s4 = (struct sockaddr_in *) &lal.addr; 854 s4 = (struct sockaddr_in *)&lal.addr;
860 s4->sin_family = AF_INET; 855 s4->sin_family = AF_INET;
861 s4->sin_port = htons (ch->ext_dns_port); 856 s4->sin_port = htons(ch->ext_dns_port);
862 s4->sin_addr = *v4; 857 s4->sin_addr = *v4;
863 lal.af = AF_INET; 858 lal.af = AF_INET;
864 lal.ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL; 859 lal.ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL;
865 check_notify_client (&lal, 860 check_notify_client(&lal,
866 ch, 861 ch,
867 add); 862 add);
868 } 863 }
869 864
870 /* (1) check if client cares. */ 865 /* (1) check if client cares. */
871 if (! ch->natted_address) 866 if (!ch->natted_address)
872 return; 867 return;
873 have_v4 = GNUNET_NO; 868 have_v4 = GNUNET_NO;
874 for (unsigned int i=0;i<ch->num_caddrs;i++) 869 for (unsigned int i = 0; i < ch->num_caddrs; i++)
875 { 870 {
876 const struct sockaddr_storage *ss = &ch->caddrs[i].ss; 871 const struct sockaddr_storage *ss = &ch->caddrs[i].ss;
877 872
878 if (AF_INET != ss->ss_family) 873 if (AF_INET != ss->ss_family)
879 continue; 874 continue;
880 have_v4 = GNUNET_YES; 875 have_v4 = GNUNET_YES;
881 break; 876 break;
882 } 877 }
883 if (GNUNET_NO == have_v4) 878 if (GNUNET_NO == have_v4)
884 return; /* IPv6-only */ 879 return; /* IPv6-only */
885 880
886 /* (2) build address info */ 881 /* (2) build address info */
887 memset (&sa, 882 memset(&sa,
888 0, 883 0,
889 sizeof (sa)); 884 sizeof(sa));
890 sa.sin_family = AF_INET; 885 sa.sin_family = AF_INET;
891 sa.sin_addr = *v4; 886 sa.sin_addr = *v4;
892 sa.sin_port = htons (0); 887 sa.sin_port = htons(0);
893 888
894 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 889 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
895 "Detected eternal IP %s, notifying client of external IP (without port)\n", 890 "Detected eternal IP %s, notifying client of external IP (without port)\n",
896 GNUNET_a2s ((const struct sockaddr *) &sa, 891 GNUNET_a2s((const struct sockaddr *)&sa,
897 sizeof (sa))); 892 sizeof(sa)));
898 /* (3) notify client of change */ 893 /* (3) notify client of change */
899 notify_client (is_nat_v4 (v4) 894 notify_client(is_nat_v4(v4)
900 ? GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_LAN 895 ? GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_LAN
901 : GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_GLOBAL, 896 : GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_GLOBAL,
902 ch, 897 ch,
903 add, 898 add,
904 &sa, 899 &sa,
905 sizeof (sa)); 900 sizeof(sa));
906} 901}
907 902
908 903
@@ -914,54 +909,54 @@ notify_client_external_ipv4_change (void *cls,
914 * @param ra IP address of the peer who wants us to connect to it 909 * @param ra IP address of the peer who wants us to connect to it
915 */ 910 */
916static void 911static void
917reversal_callback (void *cls, 912reversal_callback(void *cls,
918 const struct sockaddr_in *ra) 913 const struct sockaddr_in *ra)
919{ 914{
920 struct LocalAddressList *lal = cls; 915 struct LocalAddressList *lal = cls;
921 const struct sockaddr_in *l4; 916 const struct sockaddr_in *l4;
922 917
923 GNUNET_assert (AF_INET == lal->af); 918 GNUNET_assert(AF_INET == lal->af);
924 l4 = (const struct sockaddr_in *) &lal->addr; 919 l4 = (const struct sockaddr_in *)&lal->addr;
925 for (struct ClientHandle *ch = ch_head; 920 for (struct ClientHandle *ch = ch_head;
926 NULL != ch; 921 NULL != ch;
927 ch = ch->next) 922 ch = ch->next)
928 {
929 struct GNUNET_NAT_ConnectionReversalRequestedMessage *crrm;
930 struct GNUNET_MQ_Envelope *env;
931 int match;
932
933 /* Check if client is in applicable range for ICMP NAT traversal
934 for this local address */
935 if (! ch->natted_address)
936 continue;
937 match = GNUNET_NO;
938 for (unsigned int i=0;i<ch->num_caddrs;i++)
939 { 923 {
940 struct ClientAddress *ca = &ch->caddrs[i]; 924 struct GNUNET_NAT_ConnectionReversalRequestedMessage *crrm;
941 const struct sockaddr_in *c4; 925 struct GNUNET_MQ_Envelope *env;
942 926 int match;
943 if (AF_INET != ca->ss.ss_family) 927
944 continue; 928 /* Check if client is in applicable range for ICMP NAT traversal
945 c4 = (const struct sockaddr_in *) &ca->ss; 929 for this local address */
946 if ( (0 != c4->sin_addr.s_addr) && 930 if (!ch->natted_address)
947 (l4->sin_addr.s_addr != c4->sin_addr.s_addr) ) 931 continue;
948 continue; 932 match = GNUNET_NO;
949 match = GNUNET_YES; 933 for (unsigned int i = 0; i < ch->num_caddrs; i++)
950 break; 934 {
935 struct ClientAddress *ca = &ch->caddrs[i];
936 const struct sockaddr_in *c4;
937
938 if (AF_INET != ca->ss.ss_family)
939 continue;
940 c4 = (const struct sockaddr_in *)&ca->ss;
941 if ((0 != c4->sin_addr.s_addr) &&
942 (l4->sin_addr.s_addr != c4->sin_addr.s_addr))
943 continue;
944 match = GNUNET_YES;
945 break;
946 }
947 if (!match)
948 continue;
949
950 /* Notify applicable client about connection reversal request */
951 env = GNUNET_MQ_msg_extra(crrm,
952 sizeof(struct sockaddr_in),
953 GNUNET_MESSAGE_TYPE_NAT_CONNECTION_REVERSAL_REQUESTED);
954 GNUNET_memcpy(&crrm[1],
955 ra,
956 sizeof(struct sockaddr_in));
957 GNUNET_MQ_send(ch->mq,
958 env);
951 } 959 }
952 if (! match)
953 continue;
954
955 /* Notify applicable client about connection reversal request */
956 env = GNUNET_MQ_msg_extra (crrm,
957 sizeof (struct sockaddr_in),
958 GNUNET_MESSAGE_TYPE_NAT_CONNECTION_REVERSAL_REQUESTED);
959 GNUNET_memcpy (&crrm[1],
960 ra,
961 sizeof (struct sockaddr_in));
962 GNUNET_MQ_send (ch->mq,
963 env);
964 }
965} 960}
966 961
967 962
@@ -971,104 +966,104 @@ reversal_callback (void *cls,
971 * @param cls NULL 966 * @param cls NULL
972 */ 967 */
973static void 968static void
974run_scan (void *cls) 969run_scan(void *cls)
975{ 970{
976 struct IfcProcContext ifc_ctx; 971 struct IfcProcContext ifc_ctx;
977 int found; 972 int found;
978 int have_nat; 973 int have_nat;
979 struct LocalAddressList *lnext; 974 struct LocalAddressList *lnext;
980 975
981 scan_task = GNUNET_SCHEDULER_add_delayed (SCAN_FREQ, 976 scan_task = GNUNET_SCHEDULER_add_delayed(SCAN_FREQ,
982 &run_scan, 977 &run_scan,
983 NULL); 978 NULL);
984 memset (&ifc_ctx, 979 memset(&ifc_ctx,
985 0, 980 0,
986 sizeof (ifc_ctx)); 981 sizeof(ifc_ctx));
987 GNUNET_OS_network_interfaces_list (&ifc_proc, 982 GNUNET_OS_network_interfaces_list(&ifc_proc,
988 &ifc_ctx); 983 &ifc_ctx);
989 /* remove addresses that disappeared */ 984 /* remove addresses that disappeared */
990 for (struct LocalAddressList *lal = lal_head; 985 for (struct LocalAddressList *lal = lal_head;
991 NULL != lal; 986 NULL != lal;
992 lal = lnext) 987 lal = lnext)
993 {
994 lnext = lal->next;
995 found = GNUNET_NO;
996 for (struct LocalAddressList *pos = ifc_ctx.lal_head;
997 NULL != pos;
998 pos = pos->next)
999 { 988 {
1000 if ( (pos->af == lal->af) && 989 lnext = lal->next;
1001 (0 == memcmp (&lal->addr, 990 found = GNUNET_NO;
1002 &pos->addr, 991 for (struct LocalAddressList *pos = ifc_ctx.lal_head;
1003 (AF_INET == lal->af) 992 NULL != pos;
1004 ? sizeof (struct sockaddr_in) 993 pos = pos->next)
1005 : sizeof (struct sockaddr_in6))) ) 994 {
1006 { 995 if ((pos->af == lal->af) &&
1007 found = GNUNET_YES; 996 (0 == memcmp(&lal->addr,
1008 } 997 &pos->addr,
998 (AF_INET == lal->af)
999 ? sizeof(struct sockaddr_in)
1000 : sizeof(struct sockaddr_in6))))
1001 {
1002 found = GNUNET_YES;
1003 }
1004 }
1005 if (GNUNET_NO == found)
1006 {
1007 notify_clients(lal,
1008 GNUNET_NO);
1009 free_lal(lal);
1010 }
1009 } 1011 }
1010 if (GNUNET_NO == found)
1011 {
1012 notify_clients (lal,
1013 GNUNET_NO);
1014 free_lal (lal);
1015 }
1016 }
1017 1012
1018 /* add addresses that appeared */ 1013 /* add addresses that appeared */
1019 have_nat = GNUNET_NO; 1014 have_nat = GNUNET_NO;
1020 for (struct LocalAddressList *pos = ifc_ctx.lal_head; 1015 for (struct LocalAddressList *pos = ifc_ctx.lal_head;
1021 NULL != pos; 1016 NULL != pos;
1022 pos = ifc_ctx.lal_head) 1017 pos = ifc_ctx.lal_head)
1023 {
1024 found = GNUNET_NO;
1025 if (GNUNET_NAT_AC_LAN == (GNUNET_NAT_AC_LAN & pos->ac))
1026 have_nat = GNUNET_YES;
1027 for (struct LocalAddressList *lal = lal_head;
1028 NULL != lal;
1029 lal = lal->next)
1030 {
1031 if ( (pos->af == lal->af) &&
1032 (0 == memcmp (&lal->addr,
1033 &pos->addr,
1034 (AF_INET == lal->af)
1035 ? sizeof (struct sockaddr_in)
1036 : sizeof (struct sockaddr_in6))) )
1037 found = GNUNET_YES;
1038 }
1039 GNUNET_CONTAINER_DLL_remove (ifc_ctx.lal_head,
1040 ifc_ctx.lal_tail,
1041 pos);
1042 if (GNUNET_YES == found)
1043 {
1044 GNUNET_free (pos);
1045 }
1046 else
1047 { 1018 {
1048 notify_clients (pos, 1019 found = GNUNET_NO;
1049 GNUNET_YES); 1020 if (GNUNET_NAT_AC_LAN == (GNUNET_NAT_AC_LAN & pos->ac))
1050 GNUNET_CONTAINER_DLL_insert (lal_head, 1021 have_nat = GNUNET_YES;
1051 lal_tail, 1022 for (struct LocalAddressList *lal = lal_head;
1052 pos); 1023 NULL != lal;
1053 if ( (AF_INET == pos->af) && 1024 lal = lal->next)
1054 (NULL == pos->hc) && 1025 {
1055 (0 != (GNUNET_NAT_AC_LAN & pos->ac)) ) 1026 if ((pos->af == lal->af) &&
1056 { 1027 (0 == memcmp(&lal->addr,
1057 const struct sockaddr_in *s4 1028 &pos->addr,
1058 = (const struct sockaddr_in *) &pos->addr; 1029 (AF_INET == lal->af)
1059 1030 ? sizeof(struct sockaddr_in)
1060 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1031 : sizeof(struct sockaddr_in6))))
1061 "Found NATed local address %s, starting NAT server\n", 1032 found = GNUNET_YES;
1062 GNUNET_a2s ((const struct sockaddr *) &pos->addr, 1033 }
1063 sizeof (*s4))); 1034 GNUNET_CONTAINER_DLL_remove(ifc_ctx.lal_head,
1064 pos->hc = GN_start_gnunet_nat_server_ (&s4->sin_addr, 1035 ifc_ctx.lal_tail,
1065 &reversal_callback, 1036 pos);
1066 pos, 1037 if (GNUNET_YES == found)
1067 cfg); 1038 {
1068 } 1039 GNUNET_free(pos);
1040 }
1041 else
1042 {
1043 notify_clients(pos,
1044 GNUNET_YES);
1045 GNUNET_CONTAINER_DLL_insert(lal_head,
1046 lal_tail,
1047 pos);
1048 if ((AF_INET == pos->af) &&
1049 (NULL == pos->hc) &&
1050 (0 != (GNUNET_NAT_AC_LAN & pos->ac)))
1051 {
1052 const struct sockaddr_in *s4
1053 = (const struct sockaddr_in *)&pos->addr;
1054
1055 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1056 "Found NATed local address %s, starting NAT server\n",
1057 GNUNET_a2s((const struct sockaddr *)&pos->addr,
1058 sizeof(*s4)));
1059 pos->hc = GN_start_gnunet_nat_server_(&s4->sin_addr,
1060 &reversal_callback,
1061 pos,
1062 cfg);
1063 }
1064 }
1069 } 1065 }
1070 } 1066 GN_nat_status_changed(have_nat);
1071 GN_nat_status_changed (have_nat);
1072} 1067}
1073 1068
1074 1069
@@ -1084,81 +1079,91 @@ run_scan (void *cls)
1084 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code 1079 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
1085 */ 1080 */
1086static void 1081static void
1087upnp_addr_change_cb (void *cls, 1082upnp_addr_change_cb(void *cls,
1088 int add_remove, 1083 int add_remove,
1089 const struct sockaddr *addr, 1084 const struct sockaddr *addr,
1090 socklen_t addrlen, 1085 socklen_t addrlen,
1091 enum GNUNET_NAT_StatusCode result) 1086 enum GNUNET_NAT_StatusCode result)
1092{ 1087{
1093 struct ClientHandle *ch = cls; 1088 struct ClientHandle *ch = cls;
1094 enum GNUNET_NAT_AddressClass ac; 1089 enum GNUNET_NAT_AddressClass ac;
1095 1090
1096 switch (result) 1091 switch (result)
1097 { 1092 {
1098 case GNUNET_NAT_ERROR_SUCCESS: 1093 case GNUNET_NAT_ERROR_SUCCESS:
1099 GNUNET_assert (NULL != addr); 1094 GNUNET_assert(NULL != addr);
1100 break; 1095 break;
1101 case GNUNET_NAT_ERROR_UPNPC_FAILED: 1096
1102 case GNUNET_NAT_ERROR_UPNPC_TIMEOUT: 1097 case GNUNET_NAT_ERROR_UPNPC_FAILED:
1103 case GNUNET_NAT_ERROR_IPC_FAILURE: 1098 case GNUNET_NAT_ERROR_UPNPC_TIMEOUT:
1104 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1099 case GNUNET_NAT_ERROR_IPC_FAILURE:
1105 "Running upnpc failed: %d\n", 1100 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1106 result); 1101 "Running upnpc failed: %d\n",
1107 return; 1102 result);
1108 case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND: 1103 return;
1109 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1104
1110 "external-ip binary not found\n"); 1105 case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND:
1111 return; 1106 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1112 case GNUNET_NAT_ERROR_UPNPC_NOT_FOUND: 1107 "external-ip binary not found\n");
1113 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1108 return;
1114 "upnpc binary not found\n"); 1109
1115 return; 1110 case GNUNET_NAT_ERROR_UPNPC_NOT_FOUND:
1116 case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED: 1111 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1117 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1112 "upnpc binary not found\n");
1118 "external-ip binary could not be run\n"); 1113 return;
1119 return; 1114
1120 case GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED: 1115 case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED:
1121 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1116 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1122 "upnpc failed to create port mapping\n"); 1117 "external-ip binary could not be run\n");
1123 return; 1118 return;
1124 case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID: 1119
1125 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1120 case GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED:
1126 "Invalid output from upnpc\n"); 1121 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1127 return; 1122 "upnpc failed to create port mapping\n");
1128 case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID: 1123 return;
1129 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1124
1130 "Invalid address returned by upnpc\n"); 1125 case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID:
1131 return; 1126 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1132 default: 1127 "Invalid output from upnpc\n");
1133 GNUNET_break (0); /* should not be possible */ 1128 return;
1134 return; 1129
1135 } 1130 case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID:
1131 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1132 "Invalid address returned by upnpc\n");
1133 return;
1134
1135 default:
1136 GNUNET_break(0); /* should not be possible */
1137 return;
1138 }
1136 switch (addr->sa_family) 1139 switch (addr->sa_family)
1137 { 1140 {
1138 case AF_INET: 1141 case AF_INET:
1139 ac = is_nat_v4 (&((const struct sockaddr_in *) addr)->sin_addr) 1142 ac = is_nat_v4(&((const struct sockaddr_in *)addr)->sin_addr)
1140 ? GNUNET_NAT_AC_LAN 1143 ? GNUNET_NAT_AC_LAN
1141 : GNUNET_NAT_AC_EXTERN; 1144 : GNUNET_NAT_AC_EXTERN;
1142 break; 1145 break;
1143 case AF_INET6: 1146
1144 ac = is_nat_v6 (&((const struct sockaddr_in6 *) addr)->sin6_addr) 1147 case AF_INET6:
1145 ? GNUNET_NAT_AC_LAN 1148 ac = is_nat_v6(&((const struct sockaddr_in6 *)addr)->sin6_addr)
1146 : GNUNET_NAT_AC_EXTERN; 1149 ? GNUNET_NAT_AC_LAN
1147 break; 1150 : GNUNET_NAT_AC_EXTERN;
1148 default: 1151 break;
1149 GNUNET_break (0); 1152
1150 return; 1153 default:
1151 } 1154 GNUNET_break(0);
1152 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1155 return;
1153 "upnp external address %s: %s\n", 1156 }
1154 add_remove ? "added" : "removed", 1157 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1155 GNUNET_a2s (addr, 1158 "upnp external address %s: %s\n",
1156 addrlen)); 1159 add_remove ? "added" : "removed",
1157 notify_client (ac, 1160 GNUNET_a2s(addr,
1158 ch, 1161 addrlen));
1159 add_remove, 1162 notify_client(ac,
1160 addr, 1163 ch,
1161 addrlen); 1164 add_remove,
1165 addr,
1166 addrlen);
1162} 1167}
1163 1168
1164 1169
@@ -1171,7 +1176,7 @@ upnp_addr_change_cb (void *cls,
1171 * @param ch client handle to act upon 1176 * @param ch client handle to act upon
1172 */ 1177 */
1173static void 1178static void
1174dyndns_lookup (void *cls); 1179dyndns_lookup(void *cls);
1175 1180
1176 1181
1177/** 1182/**
@@ -1184,9 +1189,9 @@ dyndns_lookup (void *cls);
1184 * @param addrlen number of bytes in @a addr 1189 * @param addrlen number of bytes in @a addr
1185 */ 1190 */
1186static void 1191static void
1187process_external_ip (void *cls, 1192process_external_ip(void *cls,
1188 const struct sockaddr *addr, 1193 const struct sockaddr *addr,
1189 socklen_t addrlen) 1194 socklen_t addrlen)
1190{ 1195{
1191 struct ClientHandle *ch = cls; 1196 struct ClientHandle *ch = cls;
1192 struct LocalAddressList *lal; 1197 struct LocalAddressList *lal;
@@ -1195,84 +1200,86 @@ process_external_ip (void *cls,
1195 struct sockaddr_in6 *v6; 1200 struct sockaddr_in6 *v6;
1196 1201
1197 if (NULL == addr) 1202 if (NULL == addr)
1198 {
1199 struct LocalAddressList *laln;
1200
1201 ch->ext_dns = NULL;
1202 ch->ext_dns_task
1203 = GNUNET_SCHEDULER_add_delayed (dyndns_frequency,
1204 &dyndns_lookup,
1205 ch);
1206 /* Current iteration is over, remove 'old' IPs now */
1207 for (lal = ch->ext_addr_head; NULL != lal; lal = laln)
1208 { 1203 {
1209 laln = lal->next; 1204 struct LocalAddressList *laln;
1210 if (GNUNET_YES == lal->old) 1205
1211 { 1206 ch->ext_dns = NULL;
1212 GNUNET_CONTAINER_DLL_remove (ch->ext_addr_head, 1207 ch->ext_dns_task
1213 ch->ext_addr_tail, 1208 = GNUNET_SCHEDULER_add_delayed(dyndns_frequency,
1214 lal); 1209 &dyndns_lookup,
1215 check_notify_client (lal, 1210 ch);
1216 ch, 1211 /* Current iteration is over, remove 'old' IPs now */
1217 GNUNET_NO); 1212 for (lal = ch->ext_addr_head; NULL != lal; lal = laln)
1218 GNUNET_free (lal); 1213 {
1219 } 1214 laln = lal->next;
1215 if (GNUNET_YES == lal->old)
1216 {
1217 GNUNET_CONTAINER_DLL_remove(ch->ext_addr_head,
1218 ch->ext_addr_tail,
1219 lal);
1220 check_notify_client(lal,
1221 ch,
1222 GNUNET_NO);
1223 GNUNET_free(lal);
1224 }
1225 }
1226 return;
1220 } 1227 }
1221 return; 1228 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1222 } 1229 "Got IP `%s' for external address `%s'\n",
1223 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1230 GNUNET_a2s(addr,
1224 "Got IP `%s' for external address `%s'\n", 1231 addrlen),
1225 GNUNET_a2s (addr, 1232 ch->hole_external);
1226 addrlen),
1227 ch->hole_external);
1228 1233
1229 /* build sockaddr storage with port number */ 1234 /* build sockaddr storage with port number */
1230 memset (&ss, 1235 memset(&ss,
1231 0, 1236 0,
1232 sizeof (ss)); 1237 sizeof(ss));
1233 GNUNET_memcpy (&ss, 1238 GNUNET_memcpy(&ss,
1234 addr, 1239 addr,
1235 addrlen); 1240 addrlen);
1236 switch (addr->sa_family) 1241 switch (addr->sa_family)
1237 { 1242 {
1238 case AF_INET: 1243 case AF_INET:
1239 v4 = (struct sockaddr_in *) &ss; 1244 v4 = (struct sockaddr_in *)&ss;
1240 v4->sin_port = htons (ch->ext_dns_port); 1245 v4->sin_port = htons(ch->ext_dns_port);
1241 break; 1246 break;
1242 case AF_INET6: 1247
1243 v6 = (struct sockaddr_in6 *) &ss; 1248 case AF_INET6:
1244 v6->sin6_port = htons (ch->ext_dns_port); 1249 v6 = (struct sockaddr_in6 *)&ss;
1245 break; 1250 v6->sin6_port = htons(ch->ext_dns_port);
1246 default: 1251 break;
1247 GNUNET_break (0); 1252
1248 return; 1253 default:
1249 } 1254 GNUNET_break(0);
1255 return;
1256 }
1250 /* See if 'ss' matches any of our known addresses */ 1257 /* See if 'ss' matches any of our known addresses */
1251 for (lal = ch->ext_addr_head; NULL != lal; lal = lal->next) 1258 for (lal = ch->ext_addr_head; NULL != lal; lal = lal->next)
1252 {
1253 if (GNUNET_NO == lal->old)
1254 continue; /* already processed, skip */
1255 if ( (addr->sa_family == lal->addr.ss_family) &&
1256 (0 == memcmp (&ss,
1257 &lal->addr,
1258 addrlen)) )
1259 { 1259 {
1260 /* Address unchanged, remember so we do not remove */ 1260 if (GNUNET_NO == lal->old)
1261 lal->old = GNUNET_NO; 1261 continue; /* already processed, skip */
1262 return; /* done here */ 1262 if ((addr->sa_family == lal->addr.ss_family) &&
1263 (0 == memcmp(&ss,
1264 &lal->addr,
1265 addrlen)))
1266 {
1267 /* Address unchanged, remember so we do not remove */
1268 lal->old = GNUNET_NO;
1269 return; /* done here */
1270 }
1263 } 1271 }
1264 }
1265 /* notify client, and remember IP for later removal! */ 1272 /* notify client, and remember IP for later removal! */
1266 lal = GNUNET_new (struct LocalAddressList); 1273 lal = GNUNET_new(struct LocalAddressList);
1267 lal->addr = ss; 1274 lal->addr = ss;
1268 lal->af = ss.ss_family; 1275 lal->af = ss.ss_family;
1269 lal->ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL; 1276 lal->ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL;
1270 GNUNET_CONTAINER_DLL_insert (ch->ext_addr_head, 1277 GNUNET_CONTAINER_DLL_insert(ch->ext_addr_head,
1271 ch->ext_addr_tail, 1278 ch->ext_addr_tail,
1272 lal); 1279 lal);
1273 check_notify_client (lal, 1280 check_notify_client(lal,
1274 ch, 1281 ch,
1275 GNUNET_YES); 1282 GNUNET_YES);
1276} 1283}
1277 1284
1278 1285
@@ -1285,24 +1292,24 @@ process_external_ip (void *cls,
1285 * @param ch client handle to act upon 1292 * @param ch client handle to act upon
1286 */ 1293 */
1287static void 1294static void
1288dyndns_lookup (void *cls) 1295dyndns_lookup(void *cls)
1289{ 1296{
1290 struct ClientHandle *ch = cls; 1297 struct ClientHandle *ch = cls;
1291 struct LocalAddressList *lal; 1298 struct LocalAddressList *lal;
1292 1299
1293 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1300 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1294 "Performing DNS lookup for punched hole given for `%s' as `%s:%u'\n", 1301 "Performing DNS lookup for punched hole given for `%s' as `%s:%u'\n",
1295 ch->section_name, 1302 ch->section_name,
1296 ch->hole_external, 1303 ch->hole_external,
1297 (unsigned int) ch->ext_dns_port); 1304 (unsigned int)ch->ext_dns_port);
1298 for (lal = ch->ext_addr_head; NULL != lal; lal = lal->next) 1305 for (lal = ch->ext_addr_head; NULL != lal; lal = lal->next)
1299 lal->old = GNUNET_YES; 1306 lal->old = GNUNET_YES;
1300 ch->ext_dns_task = NULL; 1307 ch->ext_dns_task = NULL;
1301 ch->ext_dns = GNUNET_RESOLVER_ip_get (ch->hole_external, 1308 ch->ext_dns = GNUNET_RESOLVER_ip_get(ch->hole_external,
1302 AF_UNSPEC, 1309 AF_UNSPEC,
1303 GNUNET_TIME_UNIT_MINUTES, 1310 GNUNET_TIME_UNIT_MINUTES,
1304 &process_external_ip, 1311 &process_external_ip,
1305 ch); 1312 ch);
1306} 1313}
1307 1314
1308 1315
@@ -1318,105 +1325,105 @@ dyndns_lookup (void *cls)
1318 * @param ch client handle to act upon 1325 * @param ch client handle to act upon
1319 */ 1326 */
1320static void 1327static void
1321lookup_hole_external (struct ClientHandle *ch) 1328lookup_hole_external(struct ClientHandle *ch)
1322{ 1329{
1323 char *port; 1330 char *port;
1324 unsigned int pnum; 1331 unsigned int pnum;
1325 struct sockaddr_in *s4; 1332 struct sockaddr_in *s4;
1326 struct LocalAddressList *lal; 1333 struct LocalAddressList *lal;
1327 1334
1328 port = strrchr (ch->hole_external, ':'); 1335 port = strrchr(ch->hole_external, ':');
1329 if (NULL == port) 1336 if (NULL == port)
1330 { 1337 {
1331 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1338 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1332 _("Malformed punched hole specification `%s' (lacks port)\n"), 1339 _("Malformed punched hole specification `%s' (lacks port)\n"),
1333 ch->hole_external); 1340 ch->hole_external);
1334 return; 1341 return;
1335 } 1342 }
1336 if ( (1 != sscanf (port + 1, 1343 if ((1 != sscanf(port + 1,
1337 "%u", 1344 "%u",
1338 &pnum)) || 1345 &pnum)) ||
1339 (pnum > 65535) ) 1346 (pnum > 65535))
1340 { 1347 {
1341 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1348 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1342 _("Invalid port number in punched hole specification `%s' (lacks port)\n"), 1349 _("Invalid port number in punched hole specification `%s' (lacks port)\n"),
1343 port + 1); 1350 port + 1);
1344 return; 1351 return;
1345 } 1352 }
1346 ch->ext_dns_port = (uint16_t) pnum; 1353 ch->ext_dns_port = (uint16_t)pnum;
1347 *port = '\0'; 1354 *port = '\0';
1348 1355
1349 lal = GNUNET_new (struct LocalAddressList); 1356 lal = GNUNET_new(struct LocalAddressList);
1350 if ('[' == *ch->hole_external) 1357 if ('[' == *ch->hole_external)
1351 { 1358 {
1352 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &lal->addr; 1359 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)&lal->addr;
1360
1361 s6->sin6_family = AF_INET6;
1362 if (']' != (ch->hole_external[strlen(ch->hole_external) - 1]))
1363 {
1364 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1365 _("Malformed punched hole specification `%s' (lacks `]')\n"),
1366 ch->hole_external);
1367 GNUNET_free(lal);
1368 return;
1369 }
1370 ch->hole_external[strlen(ch->hole_external) - 1] = '\0';
1371 if (1 != inet_pton(AF_INET6,
1372 ch->hole_external + 1,
1373 &s6->sin6_addr))
1374 {
1375 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1376 _("Malformed punched hole specification `%s' (IPv6 address invalid)"),
1377 ch->hole_external + 1);
1378 GNUNET_free(lal);
1379 return;
1380 }
1381 s6->sin6_port = htons(ch->ext_dns_port);
1382 lal->af = AF_INET6;
1383 lal->ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL;
1384 GNUNET_CONTAINER_DLL_insert(ch->ext_addr_head,
1385 ch->ext_addr_tail,
1386 lal);
1387 check_notify_client(lal,
1388 ch,
1389 GNUNET_YES);
1390 return;
1391 }
1353 1392
1354 s6->sin6_family = AF_INET6; 1393 s4 = (struct sockaddr_in *)&lal->addr;
1355 if (']' != (ch->hole_external[strlen(ch->hole_external)-1])) 1394 s4->sin_family = AF_INET;
1395 if (1 == inet_pton(AF_INET,
1396 ch->hole_external,
1397 &s4->sin_addr))
1356 { 1398 {
1357 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1399 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1358 _("Malformed punched hole specification `%s' (lacks `]')\n"), 1400 "IPv4 punched hole given for `%s' via `%s:%u'\n",
1359 ch->hole_external); 1401 ch->section_name,
1360 GNUNET_free (lal); 1402 ch->hole_external,
1403 (unsigned int)ch->ext_dns_port);
1404 s4->sin_port = htons(ch->ext_dns_port);
1405 lal->af = AF_INET;
1406 lal->ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL;
1407 GNUNET_CONTAINER_DLL_insert(ch->ext_addr_head,
1408 ch->ext_addr_tail,
1409 lal);
1410 check_notify_client(lal,
1411 ch,
1412 GNUNET_YES);
1361 return; 1413 return;
1362 } 1414 }
1363 ch->hole_external[strlen(ch->hole_external)-1] = '\0'; 1415 if (0 == strcasecmp(ch->hole_external,
1364 if (1 != inet_pton (AF_INET6, 1416 "AUTO"))
1365 ch->hole_external + 1,
1366 &s6->sin6_addr))
1367 { 1417 {
1368 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1418 /* handled in #notify_client_external_ipv4_change() */
1369 _("Malformed punched hole specification `%s' (IPv6 address invalid)"), 1419 GNUNET_free(lal);
1370 ch->hole_external + 1);
1371 GNUNET_free (lal);
1372 return; 1420 return;
1373 } 1421 }
1374 s6->sin6_port = htons (ch->ext_dns_port);
1375 lal->af = AF_INET6;
1376 lal->ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL;
1377 GNUNET_CONTAINER_DLL_insert (ch->ext_addr_head,
1378 ch->ext_addr_tail,
1379 lal);
1380 check_notify_client (lal,
1381 ch,
1382 GNUNET_YES);
1383 return;
1384 }
1385
1386 s4 = (struct sockaddr_in *) &lal->addr;
1387 s4->sin_family = AF_INET;
1388 if (1 == inet_pton (AF_INET,
1389 ch->hole_external,
1390 &s4->sin_addr))
1391 {
1392 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1393 "IPv4 punched hole given for `%s' via `%s:%u'\n",
1394 ch->section_name,
1395 ch->hole_external,
1396 (unsigned int) ch->ext_dns_port);
1397 s4->sin_port = htons (ch->ext_dns_port);
1398 lal->af = AF_INET;
1399 lal->ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL;
1400 GNUNET_CONTAINER_DLL_insert (ch->ext_addr_head,
1401 ch->ext_addr_tail,
1402 lal);
1403 check_notify_client (lal,
1404 ch,
1405 GNUNET_YES);
1406 return;
1407 }
1408 if (0 == strcasecmp (ch->hole_external,
1409 "AUTO"))
1410 {
1411 /* handled in #notify_client_external_ipv4_change() */
1412 GNUNET_free (lal);
1413 return;
1414 }
1415 /* got a DNS name, trigger lookup! */ 1422 /* got a DNS name, trigger lookup! */
1416 GNUNET_free (lal); 1423 GNUNET_free(lal);
1417 ch->ext_dns_task 1424 ch->ext_dns_task
1418 = GNUNET_SCHEDULER_add_now (&dyndns_lookup, 1425 = GNUNET_SCHEDULER_add_now(&dyndns_lookup,
1419 ch); 1426 ch);
1420} 1427}
1421 1428
1422 1429
@@ -1428,132 +1435,134 @@ lookup_hole_external (struct ClientHandle *ch)
1428 * @param message the message received 1435 * @param message the message received
1429 */ 1436 */
1430static void 1437static void
1431handle_register (void *cls, 1438handle_register(void *cls,
1432 const struct GNUNET_NAT_RegisterMessage *message) 1439 const struct GNUNET_NAT_RegisterMessage *message)
1433{ 1440{
1434 struct ClientHandle *ch = cls; 1441 struct ClientHandle *ch = cls;
1435 const char *off; 1442 const char *off;
1436 size_t left; 1443 size_t left;
1437 1444
1438 if ( (0 != ch->proto) || 1445 if ((0 != ch->proto) ||
1439 (NULL != ch->caddrs) ) 1446 (NULL != ch->caddrs))
1440 {
1441 /* double registration not allowed */
1442 GNUNET_break (0);
1443 GNUNET_SERVICE_client_drop (ch->client);
1444 return;
1445 }
1446 ch->flags = message->flags;
1447 ch->proto = message->proto;
1448 ch->num_caddrs = ntohs (message->num_addrs);
1449 ch->caddrs = GNUNET_new_array (ch->num_caddrs,
1450 struct ClientAddress);
1451 left = ntohs (message->header.size) - sizeof (*message);
1452 off = (const char *) &message[1];
1453 for (unsigned int i=0;i<ch->num_caddrs;i++)
1454 {
1455 const struct sockaddr *sa = (const struct sockaddr *) off;
1456 size_t alen;
1457 uint16_t port;
1458 int is_nat;
1459
1460 if (sizeof (sa_family_t) > left)
1461 { 1447 {
1462 GNUNET_break (0); 1448 /* double registration not allowed */
1463 GNUNET_SERVICE_client_drop (ch->client); 1449 GNUNET_break(0);
1450 GNUNET_SERVICE_client_drop(ch->client);
1464 return; 1451 return;
1465 } 1452 }
1466 is_nat = GNUNET_NO; 1453 ch->flags = message->flags;
1467 switch (sa->sa_family) 1454 ch->proto = message->proto;
1455 ch->num_caddrs = ntohs(message->num_addrs);
1456 ch->caddrs = GNUNET_new_array(ch->num_caddrs,
1457 struct ClientAddress);
1458 left = ntohs(message->header.size) - sizeof(*message);
1459 off = (const char *)&message[1];
1460 for (unsigned int i = 0; i < ch->num_caddrs; i++)
1468 { 1461 {
1469 case AF_INET: 1462 const struct sockaddr *sa = (const struct sockaddr *)off;
1470 { 1463 size_t alen;
1471 struct sockaddr_in s4; 1464 uint16_t port;
1472 1465 int is_nat;
1473 GNUNET_memcpy (&s4, 1466
1474 off, 1467 if (sizeof(sa_family_t) > left)
1475 sizeof (struct sockaddr_in)); 1468 {
1476 alen = sizeof (struct sockaddr_in); 1469 GNUNET_break(0);
1477 if (is_nat_v4 (&s4.sin_addr)) 1470 GNUNET_SERVICE_client_drop(ch->client);
1478 is_nat = GNUNET_YES; 1471 return;
1479 port = ntohs (s4.sin_port); 1472 }
1480 } 1473 is_nat = GNUNET_NO;
1481 break; 1474 switch (sa->sa_family)
1482 case AF_INET6: 1475 {
1483 { 1476 case AF_INET:
1484 struct sockaddr_in6 s6; 1477 {
1485 1478 struct sockaddr_in s4;
1486 GNUNET_memcpy (&s6, 1479
1487 off, 1480 GNUNET_memcpy(&s4,
1488 sizeof (struct sockaddr_in6)); 1481 off,
1489 alen = sizeof (struct sockaddr_in6); 1482 sizeof(struct sockaddr_in));
1490 if (is_nat_v6 (&s6.sin6_addr)) 1483 alen = sizeof(struct sockaddr_in);
1491 is_nat = GNUNET_YES; 1484 if (is_nat_v4(&s4.sin_addr))
1492 port = ntohs (s6.sin6_port); 1485 is_nat = GNUNET_YES;
1493 } 1486 port = ntohs(s4.sin_port);
1494 break; 1487 }
1488 break;
1489
1490 case AF_INET6:
1491 {
1492 struct sockaddr_in6 s6;
1493
1494 GNUNET_memcpy(&s6,
1495 off,
1496 sizeof(struct sockaddr_in6));
1497 alen = sizeof(struct sockaddr_in6);
1498 if (is_nat_v6(&s6.sin6_addr))
1499 is_nat = GNUNET_YES;
1500 port = ntohs(s6.sin6_port);
1501 }
1502 break;
1503
1495#if AF_UNIX 1504#if AF_UNIX
1496 case AF_UNIX: 1505 case AF_UNIX:
1497 alen = sizeof (struct sockaddr_un); 1506 alen = sizeof(struct sockaddr_un);
1498 port = 0; 1507 port = 0;
1499 break; 1508 break;
1500#endif 1509#endif
1501 default: 1510 default:
1502 GNUNET_break (0); 1511 GNUNET_break(0);
1503 GNUNET_SERVICE_client_drop (ch->client); 1512 GNUNET_SERVICE_client_drop(ch->client);
1504 return; 1513 return;
1505 } 1514 }
1506 /* store address */ 1515 /* store address */
1507 GNUNET_assert (alen <= left); 1516 GNUNET_assert(alen <= left);
1508 GNUNET_assert (alen <= sizeof (struct sockaddr_storage)); 1517 GNUNET_assert(alen <= sizeof(struct sockaddr_storage));
1509 GNUNET_memcpy (&ch->caddrs[i].ss, 1518 GNUNET_memcpy(&ch->caddrs[i].ss,
1510 off, 1519 off,
1511 alen); 1520 alen);
1512 1521
1513 /* If applicable, try UPNPC NAT punching */ 1522 /* If applicable, try UPNPC NAT punching */
1514 if ( (is_nat) && 1523 if ((is_nat) &&
1515 (enable_upnp) && 1524 (enable_upnp) &&
1516 ( (IPPROTO_TCP == ch->proto) || 1525 ((IPPROTO_TCP == ch->proto) ||
1517 (IPPROTO_UDP == ch->proto) ) ) 1526 (IPPROTO_UDP == ch->proto)))
1518 { 1527 {
1519 ch->natted_address = GNUNET_YES; 1528 ch->natted_address = GNUNET_YES;
1520 ch->caddrs[i].mh 1529 ch->caddrs[i].mh
1521 = GNUNET_NAT_mini_map_start (port, 1530 = GNUNET_NAT_mini_map_start(port,
1522 IPPROTO_TCP == ch->proto, 1531 IPPROTO_TCP == ch->proto,
1523 &upnp_addr_change_cb, 1532 &upnp_addr_change_cb,
1524 ch); 1533 ch);
1534 }
1535
1536 off += alen;
1525 } 1537 }
1526 1538
1527 off += alen;
1528 }
1529
1530 ch->section_name 1539 ch->section_name
1531 = GNUNET_strndup (off, 1540 = GNUNET_strndup(off,
1532 ntohs (message->str_len)); 1541 ntohs(message->str_len));
1533 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1542 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1534 "Received REGISTER message from client for subsystem `%s'\n", 1543 "Received REGISTER message from client for subsystem `%s'\n",
1535 ch->section_name); 1544 ch->section_name);
1536 if (GNUNET_OK == 1545 if (GNUNET_OK ==
1537 GNUNET_CONFIGURATION_get_value_string (cfg, 1546 GNUNET_CONFIGURATION_get_value_string(cfg,
1538 ch->section_name, 1547 ch->section_name,
1539 "HOLE_EXTERNAL", 1548 "HOLE_EXTERNAL",
1540 &ch->hole_external)) 1549 &ch->hole_external))
1541 lookup_hole_external (ch); 1550 lookup_hole_external(ch);
1542 1551
1543 /* Actually send IP address list to client */ 1552 /* Actually send IP address list to client */
1544 for (struct LocalAddressList *lal = lal_head; 1553 for (struct LocalAddressList *lal = lal_head;
1545 NULL != lal; 1554 NULL != lal;
1546 lal = lal->next) 1555 lal = lal->next)
1547 { 1556 {
1548 check_notify_client (lal, 1557 check_notify_client(lal,
1549 ch, 1558 ch,
1550 GNUNET_YES); 1559 GNUNET_YES);
1551 } 1560 }
1552 /* Also consider IPv4 determined by `external-ip` */ 1561 /* Also consider IPv4 determined by `external-ip` */
1553 ch->external_monitor 1562 ch->external_monitor
1554 = GN_external_ipv4_monitor_start (&notify_client_external_ipv4_change, 1563 = GN_external_ipv4_monitor_start(&notify_client_external_ipv4_change,
1555 ch); 1564 ch);
1556 GNUNET_SERVICE_client_continue (ch->client); 1565 GNUNET_SERVICE_client_continue(ch->client);
1557} 1566}
1558 1567
1559 1568
@@ -1566,22 +1575,22 @@ handle_register (void *cls,
1566 * @return #GNUNET_OK if message is well-formed 1575 * @return #GNUNET_OK if message is well-formed
1567 */ 1576 */
1568static int 1577static int
1569check_stun (void *cls, 1578check_stun(void *cls,
1570 const struct GNUNET_NAT_HandleStunMessage *message) 1579 const struct GNUNET_NAT_HandleStunMessage *message)
1571{ 1580{
1572 size_t sa_len = ntohs (message->sender_addr_size); 1581 size_t sa_len = ntohs(message->sender_addr_size);
1573 size_t expect = sa_len + ntohs (message->payload_size); 1582 size_t expect = sa_len + ntohs(message->payload_size);
1574 1583
1575 if (ntohs (message->header.size) - sizeof (*message) != expect) 1584 if (ntohs(message->header.size) - sizeof(*message) != expect)
1576 { 1585 {
1577 GNUNET_break (0); 1586 GNUNET_break(0);
1578 return GNUNET_SYSERR; 1587 return GNUNET_SYSERR;
1579 } 1588 }
1580 if (sa_len < sizeof (sa_family_t)) 1589 if (sa_len < sizeof(sa_family_t))
1581 { 1590 {
1582 GNUNET_break (0); 1591 GNUNET_break(0);
1583 return GNUNET_SYSERR; 1592 return GNUNET_SYSERR;
1584 } 1593 }
1585 return GNUNET_OK; 1594 return GNUNET_OK;
1586} 1595}
1587 1596
@@ -1594,33 +1603,33 @@ check_stun (void *cls,
1594 * @param add #GNUNET_YES to add, #GNUNET_NO to remove 1603 * @param add #GNUNET_YES to add, #GNUNET_NO to remove
1595 */ 1604 */
1596static void 1605static void
1597notify_clients_stun_change (const struct sockaddr_in *ip, 1606notify_clients_stun_change(const struct sockaddr_in *ip,
1598 int add) 1607 int add)
1599{ 1608{
1600 for (struct ClientHandle *ch = ch_head; 1609 for (struct ClientHandle *ch = ch_head;
1601 NULL != ch; 1610 NULL != ch;
1602 ch = ch->next) 1611 ch = ch->next)
1603 { 1612 {
1604 struct sockaddr_in v4; 1613 struct sockaddr_in v4;
1605 struct GNUNET_NAT_AddressChangeNotificationMessage *msg; 1614 struct GNUNET_NAT_AddressChangeNotificationMessage *msg;
1606 struct GNUNET_MQ_Envelope *env; 1615 struct GNUNET_MQ_Envelope *env;
1607 1616
1608 if (! ch->natted_address) 1617 if (!ch->natted_address)
1609 continue; 1618 continue;
1610 v4 = *ip; 1619 v4 = *ip;
1611 v4.sin_port = htons (0); 1620 v4.sin_port = htons(0);
1612 env = GNUNET_MQ_msg_extra (msg, 1621 env = GNUNET_MQ_msg_extra(msg,
1613 sizeof (v4), 1622 sizeof(v4),
1614 GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE); 1623 GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE);
1615 msg->add_remove = htonl ((int32_t) add); 1624 msg->add_remove = htonl((int32_t)add);
1616 msg->addr_class = htonl (GNUNET_NAT_AC_EXTERN | 1625 msg->addr_class = htonl(GNUNET_NAT_AC_EXTERN |
1617 GNUNET_NAT_AC_GLOBAL); 1626 GNUNET_NAT_AC_GLOBAL);
1618 GNUNET_memcpy (&msg[1], 1627 GNUNET_memcpy(&msg[1],
1619 &v4, 1628 &v4,
1620 sizeof (v4)); 1629 sizeof(v4));
1621 GNUNET_MQ_send (ch->mq, 1630 GNUNET_MQ_send(ch->mq,
1622 env); 1631 env);
1623 } 1632 }
1624} 1633}
1625 1634
1626 1635
@@ -1632,17 +1641,17 @@ notify_clients_stun_change (const struct sockaddr_in *ip,
1632 * @param cls the `struct StunExternalIP` to drop 1641 * @param cls the `struct StunExternalIP` to drop
1633 */ 1642 */
1634static void 1643static void
1635stun_ip_timeout (void *cls) 1644stun_ip_timeout(void *cls)
1636{ 1645{
1637 struct StunExternalIP *se = cls; 1646 struct StunExternalIP *se = cls;
1638 1647
1639 se->timeout_task = NULL; 1648 se->timeout_task = NULL;
1640 notify_clients_stun_change (&se->external_addr, 1649 notify_clients_stun_change(&se->external_addr,
1641 GNUNET_NO); 1650 GNUNET_NO);
1642 GNUNET_CONTAINER_DLL_remove (se_head, 1651 GNUNET_CONTAINER_DLL_remove(se_head,
1643 se_tail, 1652 se_tail,
1644 se); 1653 se);
1645 GNUNET_free (se); 1654 GNUNET_free(se);
1646} 1655}
1647 1656
1648 1657
@@ -1654,106 +1663,107 @@ stun_ip_timeout (void *cls)
1654 * @param message the message received 1663 * @param message the message received
1655 */ 1664 */
1656static void 1665static void
1657handle_stun (void *cls, 1666handle_stun(void *cls,
1658 const struct GNUNET_NAT_HandleStunMessage *message) 1667 const struct GNUNET_NAT_HandleStunMessage *message)
1659{ 1668{
1660 struct ClientHandle *ch = cls; 1669 struct ClientHandle *ch = cls;
1661 const char *buf = (const char *) &message[1]; 1670 const char *buf = (const char *)&message[1];
1662 const struct sockaddr *sa; 1671 const struct sockaddr *sa;
1663 const void *payload; 1672 const void *payload;
1664 size_t sa_len; 1673 size_t sa_len;
1665 size_t payload_size; 1674 size_t payload_size;
1666 struct sockaddr_in external_addr; 1675 struct sockaddr_in external_addr;
1667 1676
1668 sa_len = ntohs (message->sender_addr_size); 1677 sa_len = ntohs(message->sender_addr_size);
1669 payload_size = ntohs (message->payload_size); 1678 payload_size = ntohs(message->payload_size);
1670 sa = (const struct sockaddr *) &buf[0]; 1679 sa = (const struct sockaddr *)&buf[0];
1671 payload = (const struct sockaddr *) &buf[sa_len]; 1680 payload = (const struct sockaddr *)&buf[sa_len];
1672 switch (sa->sa_family) 1681 switch (sa->sa_family)
1673 {
1674 case AF_INET:
1675 if (sa_len != sizeof (struct sockaddr_in))
1676 {
1677 GNUNET_break (0);
1678 GNUNET_SERVICE_client_drop (ch->client);
1679 return;
1680 }
1681 break;
1682 case AF_INET6:
1683 if (sa_len != sizeof (struct sockaddr_in6))
1684 { 1682 {
1685 GNUNET_break (0); 1683 case AF_INET:
1686 GNUNET_SERVICE_client_drop (ch->client); 1684 if (sa_len != sizeof(struct sockaddr_in))
1687 return; 1685 {
1686 GNUNET_break(0);
1687 GNUNET_SERVICE_client_drop(ch->client);
1688 return;
1689 }
1690 break;
1691
1692 case AF_INET6:
1693 if (sa_len != sizeof(struct sockaddr_in6))
1694 {
1695 GNUNET_break(0);
1696 GNUNET_SERVICE_client_drop(ch->client);
1697 return;
1698 }
1699 break;
1688 } 1700 }
1689 break; 1701 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1690 } 1702 "Received HANDLE_STUN message from client\n");
1691 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1692 "Received HANDLE_STUN message from client\n");
1693 if (GNUNET_OK == 1703 if (GNUNET_OK ==
1694 GNUNET_NAT_stun_handle_packet_ (payload, 1704 GNUNET_NAT_stun_handle_packet_(payload,
1695 payload_size, 1705 payload_size,
1696 &external_addr)) 1706 &external_addr))
1697 {
1698 /* We now know that a server at "sa" claims that
1699 we are visible at IP "external_addr".
1700
1701 We should (for some fixed period of time) tell
1702 all of our clients that listen to a NAT'ed address
1703 that they might want to consider the given 'external_ip'
1704 as their public IP address (this includes TCP and UDP
1705 clients, even if only UDP sends STUN requests).
1706
1707 If we do not get a renewal, the "external_addr" should be
1708 removed again. The timeout frequency should be configurable
1709 (with a sane default), so that the UDP plugin can tell how
1710 often to re-request STUN.
1711 */
1712 struct StunExternalIP *se;
1713
1714 /* Check if we had a prior response from this STUN server */
1715 for (se = se_head; NULL != se; se = se->next)
1716 { 1707 {
1717 if ( (se->stun_server_addr_len != sa_len) || 1708 /* We now know that a server at "sa" claims that
1718 (0 != memcmp (sa, 1709 we are visible at IP "external_addr".
1719 &se->stun_server_addr, 1710
1720 sa_len)) ) 1711 We should (for some fixed period of time) tell
1721 continue; /* different STUN server */ 1712 all of our clients that listen to a NAT'ed address
1722 if (0 != GNUNET_memcmp (&external_addr, 1713 that they might want to consider the given 'external_ip'
1723 &se->external_addr)) 1714 as their public IP address (this includes TCP and UDP
1724 { 1715 clients, even if only UDP sends STUN requests).
1725 /* external IP changed, update! */ 1716
1726 notify_clients_stun_change (&se->external_addr, 1717 If we do not get a renewal, the "external_addr" should be
1727 GNUNET_NO); 1718 removed again. The timeout frequency should be configurable
1728 se->external_addr = external_addr; 1719 (with a sane default), so that the UDP plugin can tell how
1729 notify_clients_stun_change (&se->external_addr, 1720 often to re-request STUN.
1730 GNUNET_YES); 1721 */
1731 } 1722 struct StunExternalIP *se;
1732 /* update timeout */ 1723
1733 GNUNET_SCHEDULER_cancel (se->timeout_task); 1724 /* Check if we had a prior response from this STUN server */
1734 se->timeout_task 1725 for (se = se_head; NULL != se; se = se->next)
1735 = GNUNET_SCHEDULER_add_delayed (stun_stale_timeout, 1726 {
1736 &stun_ip_timeout, 1727 if ((se->stun_server_addr_len != sa_len) ||
1737 se); 1728 (0 != memcmp(sa,
1738 return; 1729 &se->stun_server_addr,
1730 sa_len)))
1731 continue; /* different STUN server */
1732 if (0 != GNUNET_memcmp(&external_addr,
1733 &se->external_addr))
1734 {
1735 /* external IP changed, update! */
1736 notify_clients_stun_change(&se->external_addr,
1737 GNUNET_NO);
1738 se->external_addr = external_addr;
1739 notify_clients_stun_change(&se->external_addr,
1740 GNUNET_YES);
1741 }
1742 /* update timeout */
1743 GNUNET_SCHEDULER_cancel(se->timeout_task);
1744 se->timeout_task
1745 = GNUNET_SCHEDULER_add_delayed(stun_stale_timeout,
1746 &stun_ip_timeout,
1747 se);
1748 return;
1749 }
1750 /* STUN server is completely new, create fresh entry */
1751 se = GNUNET_new(struct StunExternalIP);
1752 se->external_addr = external_addr;
1753 GNUNET_memcpy(&se->stun_server_addr,
1754 sa,
1755 sa_len);
1756 se->stun_server_addr_len = sa_len;
1757 se->timeout_task = GNUNET_SCHEDULER_add_delayed(stun_stale_timeout,
1758 &stun_ip_timeout,
1759 se);
1760 GNUNET_CONTAINER_DLL_insert(se_head,
1761 se_tail,
1762 se);
1763 notify_clients_stun_change(&se->external_addr,
1764 GNUNET_NO);
1739 } 1765 }
1740 /* STUN server is completely new, create fresh entry */ 1766 GNUNET_SERVICE_client_continue(ch->client);
1741 se = GNUNET_new (struct StunExternalIP);
1742 se->external_addr = external_addr;
1743 GNUNET_memcpy (&se->stun_server_addr,
1744 sa,
1745 sa_len);
1746 se->stun_server_addr_len = sa_len;
1747 se->timeout_task = GNUNET_SCHEDULER_add_delayed (stun_stale_timeout,
1748 &stun_ip_timeout,
1749 se);
1750 GNUNET_CONTAINER_DLL_insert (se_head,
1751 se_tail,
1752 se);
1753 notify_clients_stun_change (&se->external_addr,
1754 GNUNET_NO);
1755 }
1756 GNUNET_SERVICE_client_continue (ch->client);
1757} 1767}
1758 1768
1759 1769
@@ -1767,18 +1777,18 @@ handle_stun (void *cls,
1767 * @return #GNUNET_OK if message is well-formed 1777 * @return #GNUNET_OK if message is well-formed
1768 */ 1778 */
1769static int 1779static int
1770check_request_connection_reversal (void *cls, 1780check_request_connection_reversal(void *cls,
1771 const struct GNUNET_NAT_RequestConnectionReversalMessage *message) 1781 const struct GNUNET_NAT_RequestConnectionReversalMessage *message)
1772{ 1782{
1773 size_t expect; 1783 size_t expect;
1774 1784
1775 expect = ntohs (message->local_addr_size) 1785 expect = ntohs(message->local_addr_size)
1776 + ntohs (message->remote_addr_size); 1786 + ntohs(message->remote_addr_size);
1777 if (ntohs (message->header.size) - sizeof (*message) != expect) 1787 if (ntohs(message->header.size) - sizeof(*message) != expect)
1778 { 1788 {
1779 GNUNET_break (0); 1789 GNUNET_break(0);
1780 return GNUNET_SYSERR; 1790 return GNUNET_SYSERR;
1781 } 1791 }
1782 return GNUNET_OK; 1792 return GNUNET_OK;
1783} 1793}
1784 1794
@@ -1791,48 +1801,48 @@ check_request_connection_reversal (void *cls,
1791 * @param message the message received 1801 * @param message the message received
1792 */ 1802 */
1793static void 1803static void
1794handle_request_connection_reversal (void *cls, 1804handle_request_connection_reversal(void *cls,
1795 const struct GNUNET_NAT_RequestConnectionReversalMessage *message) 1805 const struct GNUNET_NAT_RequestConnectionReversalMessage *message)
1796{ 1806{
1797 struct ClientHandle *ch = cls; 1807 struct ClientHandle *ch = cls;
1798 const char *buf = (const char *) &message[1]; 1808 const char *buf = (const char *)&message[1];
1799 size_t local_sa_len = ntohs (message->local_addr_size); 1809 size_t local_sa_len = ntohs(message->local_addr_size);
1800 size_t remote_sa_len = ntohs (message->remote_addr_size); 1810 size_t remote_sa_len = ntohs(message->remote_addr_size);
1801 struct sockaddr_in l4; 1811 struct sockaddr_in l4;
1802 struct sockaddr_in r4; 1812 struct sockaddr_in r4;
1803 int ret; 1813 int ret;
1804 1814
1805 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1815 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1806 "Received REQUEST CONNECTION REVERSAL message from client\n"); 1816 "Received REQUEST CONNECTION REVERSAL message from client\n");
1807 if (local_sa_len != sizeof (struct sockaddr_in)) 1817 if (local_sa_len != sizeof(struct sockaddr_in))
1808 { 1818 {
1809 GNUNET_break_op (0); 1819 GNUNET_break_op(0);
1810 GNUNET_SERVICE_client_drop (ch->client); 1820 GNUNET_SERVICE_client_drop(ch->client);
1811 return; 1821 return;
1812 } 1822 }
1813 if (remote_sa_len != sizeof (struct sockaddr_in)) 1823 if (remote_sa_len != sizeof(struct sockaddr_in))
1814 { 1824 {
1815 GNUNET_break_op (0); 1825 GNUNET_break_op(0);
1816 GNUNET_SERVICE_client_drop (ch->client); 1826 GNUNET_SERVICE_client_drop(ch->client);
1817 return; 1827 return;
1818 } 1828 }
1819 GNUNET_memcpy (&l4, 1829 GNUNET_memcpy(&l4,
1820 buf, 1830 buf,
1821 sizeof (struct sockaddr_in)); 1831 sizeof(struct sockaddr_in));
1822 GNUNET_break_op (AF_INET == l4.sin_family); 1832 GNUNET_break_op(AF_INET == l4.sin_family);
1823 buf += sizeof (struct sockaddr_in); 1833 buf += sizeof(struct sockaddr_in);
1824 GNUNET_memcpy (&r4, 1834 GNUNET_memcpy(&r4,
1825 buf, 1835 buf,
1826 sizeof (struct sockaddr_in)); 1836 sizeof(struct sockaddr_in));
1827 GNUNET_break_op (AF_INET == r4.sin_family); 1837 GNUNET_break_op(AF_INET == r4.sin_family);
1828 ret = GN_request_connection_reversal (&l4.sin_addr, 1838 ret = GN_request_connection_reversal(&l4.sin_addr,
1829 ntohs (l4.sin_port), 1839 ntohs(l4.sin_port),
1830 &r4.sin_addr, 1840 &r4.sin_addr,
1831 cfg); 1841 cfg);
1832 if (GNUNET_OK != ret) 1842 if (GNUNET_OK != ret)
1833 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1843 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1834 _("Connection reversal request failed\n")); 1844 _("Connection reversal request failed\n"));
1835 GNUNET_SERVICE_client_continue (ch->client); 1845 GNUNET_SERVICE_client_continue(ch->client);
1836} 1846}
1837 1847
1838 1848
@@ -1842,31 +1852,31 @@ handle_request_connection_reversal (void *cls,
1842 * @param cls unused 1852 * @param cls unused
1843 */ 1853 */
1844static void 1854static void
1845shutdown_task (void *cls) 1855shutdown_task(void *cls)
1846{ 1856{
1847 struct StunExternalIP *se; 1857 struct StunExternalIP *se;
1848 1858
1849 while (NULL != (se = se_head)) 1859 while (NULL != (se = se_head))
1850 { 1860 {
1851 GNUNET_CONTAINER_DLL_remove (se_head, 1861 GNUNET_CONTAINER_DLL_remove(se_head,
1852 se_tail, 1862 se_tail,
1853 se); 1863 se);
1854 GNUNET_SCHEDULER_cancel (se->timeout_task); 1864 GNUNET_SCHEDULER_cancel(se->timeout_task);
1855 GNUNET_free (se); 1865 GNUNET_free(se);
1856 } 1866 }
1857 GN_nat_status_changed (GNUNET_NO); 1867 GN_nat_status_changed(GNUNET_NO);
1858 if (NULL != scan_task) 1868 if (NULL != scan_task)
1859 { 1869 {
1860 GNUNET_SCHEDULER_cancel (scan_task); 1870 GNUNET_SCHEDULER_cancel(scan_task);
1861 scan_task = NULL; 1871 scan_task = NULL;
1862 } 1872 }
1863 if (NULL != stats) 1873 if (NULL != stats)
1864 { 1874 {
1865 GNUNET_STATISTICS_destroy (stats, 1875 GNUNET_STATISTICS_destroy(stats,
1866 GNUNET_NO); 1876 GNUNET_NO);
1867 stats = NULL; 1877 stats = NULL;
1868 } 1878 }
1869 destroy_lal (); 1879 destroy_lal();
1870} 1880}
1871 1881
1872 1882
@@ -1878,49 +1888,49 @@ shutdown_task (void *cls)
1878 * @param service the initialized service 1888 * @param service the initialized service
1879 */ 1889 */
1880static void 1890static void
1881run (void *cls, 1891run(void *cls,
1882 const struct GNUNET_CONFIGURATION_Handle *c, 1892 const struct GNUNET_CONFIGURATION_Handle *c,
1883 struct GNUNET_SERVICE_Handle *service) 1893 struct GNUNET_SERVICE_Handle *service)
1884{ 1894{
1885 cfg = c; 1895 cfg = c;
1886 if (GNUNET_OK != 1896 if (GNUNET_OK !=
1887 GNUNET_CONFIGURATION_get_value_time (cfg, 1897 GNUNET_CONFIGURATION_get_value_time(cfg,
1888 "NAT", 1898 "NAT",
1889 "STUN_STALE", 1899 "STUN_STALE",
1890 &stun_stale_timeout)) 1900 &stun_stale_timeout))
1891 stun_stale_timeout = GNUNET_TIME_UNIT_HOURS; 1901 stun_stale_timeout = GNUNET_TIME_UNIT_HOURS;
1892 1902
1893 /* Check for UPnP */ 1903 /* Check for UPnP */
1894 enable_upnp 1904 enable_upnp
1895 = GNUNET_CONFIGURATION_get_value_yesno (cfg, 1905 = GNUNET_CONFIGURATION_get_value_yesno(cfg,
1896 "NAT", 1906 "NAT",
1897 "ENABLE_UPNP"); 1907 "ENABLE_UPNP");
1898 if (GNUNET_YES == enable_upnp) 1908 if (GNUNET_YES == enable_upnp)
1899 {
1900 /* check if it works */
1901 if (GNUNET_SYSERR ==
1902 GNUNET_OS_check_helper_binary ("upnpc",
1903 GNUNET_NO,
1904 NULL))
1905 { 1909 {
1906 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1910 /* check if it works */
1907 _("UPnP enabled in configuration, but UPnP client `upnpc` command not found, disabling UPnP\n")); 1911 if (GNUNET_SYSERR ==
1908 enable_upnp = GNUNET_SYSERR; 1912 GNUNET_OS_check_helper_binary("upnpc",
1913 GNUNET_NO,
1914 NULL))
1915 {
1916 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1917 _("UPnP enabled in configuration, but UPnP client `upnpc` command not found, disabling UPnP\n"));
1918 enable_upnp = GNUNET_SYSERR;
1919 }
1909 } 1920 }
1910 }
1911 if (GNUNET_OK != 1921 if (GNUNET_OK !=
1912 GNUNET_CONFIGURATION_get_value_time (cfg, 1922 GNUNET_CONFIGURATION_get_value_time(cfg,
1913 "nat", 1923 "nat",
1914 "DYNDNS_FREQUENCY", 1924 "DYNDNS_FREQUENCY",
1915 &dyndns_frequency)) 1925 &dyndns_frequency))
1916 dyndns_frequency = DYNDNS_FREQUENCY; 1926 dyndns_frequency = DYNDNS_FREQUENCY;
1917 1927
1918 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, 1928 GNUNET_SCHEDULER_add_shutdown(&shutdown_task,
1919 NULL); 1929 NULL);
1920 stats = GNUNET_STATISTICS_create ("nat", 1930 stats = GNUNET_STATISTICS_create("nat",
1921 cfg); 1931 cfg);
1922 scan_task = GNUNET_SCHEDULER_add_now (&run_scan, 1932 scan_task = GNUNET_SCHEDULER_add_now(&run_scan,
1923 NULL); 1933 NULL);
1924} 1934}
1925 1935
1926 1936
@@ -1933,18 +1943,18 @@ run (void *cls,
1933 * @return a `struct ClientHandle` 1943 * @return a `struct ClientHandle`
1934 */ 1944 */
1935static void * 1945static void *
1936client_connect_cb (void *cls, 1946client_connect_cb(void *cls,
1937 struct GNUNET_SERVICE_Client *c, 1947 struct GNUNET_SERVICE_Client *c,
1938 struct GNUNET_MQ_Handle *mq) 1948 struct GNUNET_MQ_Handle *mq)
1939{ 1949{
1940 struct ClientHandle *ch; 1950 struct ClientHandle *ch;
1941 1951
1942 ch = GNUNET_new (struct ClientHandle); 1952 ch = GNUNET_new(struct ClientHandle);
1943 ch->mq = mq; 1953 ch->mq = mq;
1944 ch->client = c; 1954 ch->client = c;
1945 GNUNET_CONTAINER_DLL_insert (ch_head, 1955 GNUNET_CONTAINER_DLL_insert(ch_head,
1946 ch_tail, 1956 ch_tail,
1947 ch); 1957 ch);
1948 return ch; 1958 return ch;
1949} 1959}
1950 1960
@@ -1957,50 +1967,50 @@ client_connect_cb (void *cls,
1957 * @param internal_cls a `struct ClientHandle *` 1967 * @param internal_cls a `struct ClientHandle *`
1958 */ 1968 */
1959static void 1969static void
1960client_disconnect_cb (void *cls, 1970client_disconnect_cb(void *cls,
1961 struct GNUNET_SERVICE_Client *c, 1971 struct GNUNET_SERVICE_Client *c,
1962 void *internal_cls) 1972 void *internal_cls)
1963{ 1973{
1964 struct ClientHandle *ch = internal_cls; 1974 struct ClientHandle *ch = internal_cls;
1965 struct LocalAddressList *lal; 1975 struct LocalAddressList *lal;
1966 1976
1967 GNUNET_CONTAINER_DLL_remove (ch_head, 1977 GNUNET_CONTAINER_DLL_remove(ch_head,
1968 ch_tail, 1978 ch_tail,
1969 ch); 1979 ch);
1970 for (unsigned int i=0;i<ch->num_caddrs;i++) 1980 for (unsigned int i = 0; i < ch->num_caddrs; i++)
1971 {
1972 if (NULL != ch->caddrs[i].mh)
1973 { 1981 {
1974 GNUNET_NAT_mini_map_stop (ch->caddrs[i].mh); 1982 if (NULL != ch->caddrs[i].mh)
1975 ch->caddrs[i].mh = NULL; 1983 {
1984 GNUNET_NAT_mini_map_stop(ch->caddrs[i].mh);
1985 ch->caddrs[i].mh = NULL;
1986 }
1976 } 1987 }
1977 } 1988 GNUNET_free_non_null(ch->caddrs);
1978 GNUNET_free_non_null (ch->caddrs);
1979 while (NULL != (lal = ch->ext_addr_head)) 1989 while (NULL != (lal = ch->ext_addr_head))
1980 { 1990 {
1981 GNUNET_CONTAINER_DLL_remove (ch->ext_addr_head, 1991 GNUNET_CONTAINER_DLL_remove(ch->ext_addr_head,
1982 ch->ext_addr_tail, 1992 ch->ext_addr_tail,
1983 lal); 1993 lal);
1984 GNUNET_free (lal); 1994 GNUNET_free(lal);
1985 } 1995 }
1986 if (NULL != ch->ext_dns_task) 1996 if (NULL != ch->ext_dns_task)
1987 { 1997 {
1988 GNUNET_SCHEDULER_cancel (ch->ext_dns_task); 1998 GNUNET_SCHEDULER_cancel(ch->ext_dns_task);
1989 ch->ext_dns_task = NULL; 1999 ch->ext_dns_task = NULL;
1990 } 2000 }
1991 if (NULL != ch->external_monitor) 2001 if (NULL != ch->external_monitor)
1992 { 2002 {
1993 GN_external_ipv4_monitor_stop (ch->external_monitor); 2003 GN_external_ipv4_monitor_stop(ch->external_monitor);
1994 ch->external_monitor = NULL; 2004 ch->external_monitor = NULL;
1995 } 2005 }
1996 if (NULL != ch->ext_dns) 2006 if (NULL != ch->ext_dns)
1997 { 2007 {
1998 GNUNET_RESOLVER_request_cancel (ch->ext_dns); 2008 GNUNET_RESOLVER_request_cancel(ch->ext_dns);
1999 ch->ext_dns = NULL; 2009 ch->ext_dns = NULL;
2000 } 2010 }
2001 GNUNET_free_non_null (ch->hole_external); 2011 GNUNET_free_non_null(ch->hole_external);
2002 GNUNET_free_non_null (ch->section_name); 2012 GNUNET_free_non_null(ch->section_name);
2003 GNUNET_free (ch); 2013 GNUNET_free(ch);
2004} 2014}
2005 2015
2006 2016
@@ -2008,25 +2018,25 @@ client_disconnect_cb (void *cls,
2008 * Define "main" method using service macro. 2018 * Define "main" method using service macro.
2009 */ 2019 */
2010GNUNET_SERVICE_MAIN 2020GNUNET_SERVICE_MAIN
2011("nat", 2021 ("nat",
2012 GNUNET_SERVICE_OPTION_NONE, 2022 GNUNET_SERVICE_OPTION_NONE,
2013 &run, 2023 &run,
2014 &client_connect_cb, 2024 &client_connect_cb,
2015 &client_disconnect_cb, 2025 &client_disconnect_cb,
2016 NULL, 2026 NULL,
2017 GNUNET_MQ_hd_var_size (register, 2027 GNUNET_MQ_hd_var_size(register,
2018 GNUNET_MESSAGE_TYPE_NAT_REGISTER, 2028 GNUNET_MESSAGE_TYPE_NAT_REGISTER,
2019 struct GNUNET_NAT_RegisterMessage, 2029 struct GNUNET_NAT_RegisterMessage,
2020 NULL), 2030 NULL),
2021 GNUNET_MQ_hd_var_size (stun, 2031 GNUNET_MQ_hd_var_size(stun,
2022 GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN, 2032 GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN,
2023 struct GNUNET_NAT_HandleStunMessage, 2033 struct GNUNET_NAT_HandleStunMessage,
2024 NULL), 2034 NULL),
2025 GNUNET_MQ_hd_var_size (request_connection_reversal, 2035 GNUNET_MQ_hd_var_size(request_connection_reversal,
2026 GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL, 2036 GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL,
2027 struct GNUNET_NAT_RequestConnectionReversalMessage, 2037 struct GNUNET_NAT_RequestConnectionReversalMessage,
2028 NULL), 2038 NULL),
2029 GNUNET_MQ_handler_end ()); 2039 GNUNET_MQ_handler_end());
2030 2040
2031 2041
2032#if defined(LINUX) && defined(__GLIBC__) 2042#if defined(LINUX) && defined(__GLIBC__)
@@ -2036,11 +2046,11 @@ GNUNET_SERVICE_MAIN
2036 * MINIMIZE heap size (way below 128k) since this process doesn't need much. 2046 * MINIMIZE heap size (way below 128k) since this process doesn't need much.
2037 */ 2047 */
2038void __attribute__ ((constructor)) 2048void __attribute__ ((constructor))
2039GNUNET_ARM_memory_init () 2049GNUNET_ARM_memory_init()
2040{ 2050{
2041 mallopt (M_TRIM_THRESHOLD, 4 * 1024); 2051 mallopt(M_TRIM_THRESHOLD, 4 * 1024);
2042 mallopt (M_TOP_PAD, 1 * 1024); 2052 mallopt(M_TOP_PAD, 1 * 1024);
2043 malloc_trim (0); 2053 malloc_trim(0);
2044} 2054}
2045#endif 2055#endif
2046 2056