aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/gnunet_nat_service.h8
-rw-r--r--src/nat/gnunet-service-nat.c86
2 files changed, 86 insertions, 8 deletions
diff --git a/src/include/gnunet_nat_service.h b/src/include/gnunet_nat_service.h
index a42d1d7e6..4df17b531 100644
--- a/src/include/gnunet_nat_service.h
+++ b/src/include/gnunet_nat_service.h
@@ -114,11 +114,13 @@ enum GNUNET_NAT_AddressClass
114 GNUNET_NAT_AC_LOOPBACK = 64, 114 GNUNET_NAT_AC_LOOPBACK = 64,
115 115
116 /** 116 /**
117 * Addresses that should be our global external IP address 117 * Addresses that should be our external IP address
118 * on the outside of a NAT. Might be incorrectly determined. 118 * on the outside of a NAT. Might be incorrectly determined.
119 * Used as a bit in combination with #GNUNET_NAT_AC_GLOBAL. 119 * Used as a bit in combination with #GNUNET_NAT_AC_GLOBAL,
120 * or in case of double-NAT with
121 * #GNUNET_NAT_AC_LAN.
120 */ 122 */
121 GNUNET_NAT_AC_GLOBAL_EXTERN = 128, 123 GNUNET_NAT_AC_EXTERN = 128,
122 124
123 /** 125 /**
124 * Bitmask for "any" address. 126 * Bitmask for "any" address.
diff --git a/src/nat/gnunet-service-nat.c b/src/nat/gnunet-service-nat.c
index 9ad8db45a..e7173e57a 100644
--- a/src/nat/gnunet-service-nat.c
+++ b/src/nat/gnunet-service-nat.c
@@ -724,6 +724,29 @@ check_notify_client (struct LocalAddressList *delta,
724 if (AF_INET != ch->caddrs[i].ss.ss_family) 724 if (AF_INET != ch->caddrs[i].ss.ss_family)
725 return; /* IPv4 not relevant */ 725 return; /* IPv4 not relevant */
726 c4 = (const struct sockaddr_in *) &ch->caddrs[i].ss; 726 c4 = (const struct sockaddr_in *) &ch->caddrs[i].ss;
727 if ( match_ipv4 ("127.0.0.1", &c4->sin_addr, 8) &&
728 (0 != c4->sin_addr.s_addr) &&
729 (! match_ipv4 ("127.0.0.1", &v4.sin_addr, 8)) )
730 continue; /* bound to loopback, but this is not loopback */
731 if ( (! match_ipv4 ("127.0.0.1", &c4->sin_addr, 8) ) &&
732 (0 != c4->sin_addr.s_addr) &&
733 match_ipv4 ("127.0.0.1", &v4.sin_addr, 8) )
734 continue; /* bound to non-loopback, but this is loopback */
735 if ( (0 != (ch->flags & GNUNET_NAT_AC_EXTERN)) &&
736 (0 != c4->sin_addr.s_addr) &&
737 (! is_nat_v4 (&v4.sin_addr)) )
738 continue; /* based on external-IP, but this IP is not
739 from private address range. */
740 if ( (0 != memcmp (&v4.sin_addr,
741 &c4->sin_addr,
742 sizeof (struct in_addr))) &&
743 (0 != c4->sin_addr.s_addr) &&
744 ( (! is_nat_v4 (&c4->sin_addr)) ||
745 (0 == (ch->flags & GNUNET_NAT_AC_EXTERN))) )
746 continue; /* this IP is not from private address range,
747 and IP does not match. */
748
749 /* OK, IP seems relevant, notify client */
727 v4.sin_port = c4->sin_port; 750 v4.sin_port = c4->sin_port;
728 notify_client (delta->ac, 751 notify_client (delta->ac,
729 ch, 752 ch,
@@ -744,6 +767,46 @@ check_notify_client (struct LocalAddressList *delta,
744 if (AF_INET6 != ch->caddrs[i].ss.ss_family) 767 if (AF_INET6 != ch->caddrs[i].ss.ss_family)
745 return; /* IPv4 not relevant */ 768 return; /* IPv4 not relevant */
746 c6 = (const struct sockaddr_in6 *) &ch->caddrs[i].ss; 769 c6 = (const struct sockaddr_in6 *) &ch->caddrs[i].ss;
770 if ( match_ipv6 ("::1", &c6->sin6_addr, 128) &&
771 (0 != memcmp (&c6->sin6_addr,
772 &in6addr_any,
773 sizeof (struct in6_addr))) &&
774 (! match_ipv6 ("::1", &v6.sin6_addr, 128)) )
775 continue; /* bound to loopback, but this is not loopback */
776 if ( (! match_ipv6 ("::1", &c6->sin6_addr, 128) ) &&
777 (0 != memcmp (&c6->sin6_addr,
778 &in6addr_any,
779 sizeof (struct in6_addr))) &&
780 match_ipv6 ("::1", &v6.sin6_addr, 128) )
781 continue; /* bound to non-loopback, but this is loopback */
782 if ( (0 != (ch->flags & GNUNET_NAT_AC_EXTERN)) &&
783 (0 != memcmp (&c6->sin6_addr,
784 &in6addr_any,
785 sizeof (struct in6_addr))) &&
786 (! is_nat_v6 (&v6.sin6_addr)) )
787 continue; /* based on external-IP, but this IP is not
788 from private address range. */
789 if ( (0 != memcmp (&v6.sin6_addr,
790 &c6->sin6_addr,
791 sizeof (struct in6_addr))) &&
792 (0 != memcmp (&c6->sin6_addr,
793 &in6addr_any,
794 sizeof (struct in6_addr))) &&
795 (! is_nat_v6 (&c6->sin6_addr)) )
796 continue; /* this IP is not from private address range,
797 and IP does not match. */
798 if ( (match_ipv6 ("fe80::", &c6->sin6_addr, 10)) &&
799 (0 != memcmp (&c6->sin6_addr,
800 &in6addr_any,
801 sizeof (struct in6_addr))) &&
802 (0 != memcmp (&v6.sin6_addr,
803 &c6->sin6_addr,
804 sizeof (struct in6_addr))) &&
805 (0 == (delta->ac & GNUNET_NAT_AC_EXTERN)) )
806 continue; /* client bound to link-local, and the other address
807 does not match and is not an external IP */
808
809 /* OK, IP seems relevant, notify client */
747 v6.sin6_port = c6->sin6_port; 810 v6.sin6_port = c6->sin6_port;
748 notify_client (delta->ac, 811 notify_client (delta->ac,
749 ch, 812 ch,
@@ -826,8 +889,8 @@ check_notify_client_external_ipv4_change (const struct in_addr *v4,
826 889
827 /* (3) notify client of change */ 890 /* (3) notify client of change */
828 notify_client (is_nat_v4 (v4) 891 notify_client (is_nat_v4 (v4)
829 ? GNUNET_NAT_AC_LAN_PRIVATE 892 ? GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_LAN_PRIVATE
830 : GNUNET_NAT_AC_GLOBAL_EXTERN, 893 : GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_GLOBAL,
831 ch, 894 ch,
832 add, 895 add,
833 &sa, 896 &sa,
@@ -879,6 +942,8 @@ handle_external_ip (void *cls,
879 const struct in_addr *addr, 942 const struct in_addr *addr,
880 enum GNUNET_NAT_StatusCode result) 943 enum GNUNET_NAT_StatusCode result)
881{ 944{
945 char buf[INET_ADDRSTRLEN];
946
882 probe_external_ip_op = NULL; 947 probe_external_ip_op = NULL;
883 GNUNET_SCHEDULER_cancel (probe_external_ip_task); 948 GNUNET_SCHEDULER_cancel (probe_external_ip_task);
884 probe_external_ip_task 949 probe_external_ip_task
@@ -892,6 +957,12 @@ handle_external_ip (void *cls,
892 case GNUNET_NAT_ERROR_SUCCESS: 957 case GNUNET_NAT_ERROR_SUCCESS:
893 if (addr->s_addr == mini_external_ipv4.s_addr) 958 if (addr->s_addr == mini_external_ipv4.s_addr)
894 return; /* not change */ 959 return; /* not change */
960 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
961 "Our external IP is now %s\n",
962 inet_ntop (AF_INET,
963 addr,
964 buf,
965 sizeof (buf)));
895 if (0 != mini_external_ipv4.s_addr) 966 if (0 != mini_external_ipv4.s_addr)
896 notify_clients_external_ipv4_change (GNUNET_NO, 967 notify_clients_external_ipv4_change (GNUNET_NO,
897 &mini_external_ipv4); 968 &mini_external_ipv4);
@@ -1093,17 +1164,22 @@ upnp_addr_change_cb (void *cls,
1093 case AF_INET: 1164 case AF_INET:
1094 ac = is_nat_v4 (&((const struct sockaddr_in *) addr)->sin_addr) 1165 ac = is_nat_v4 (&((const struct sockaddr_in *) addr)->sin_addr)
1095 ? GNUNET_NAT_AC_LAN_PRIVATE 1166 ? GNUNET_NAT_AC_LAN_PRIVATE
1096 : GNUNET_NAT_AC_GLOBAL_EXTERN; 1167 : GNUNET_NAT_AC_EXTERN;
1097 break; 1168 break;
1098 case AF_INET6: 1169 case AF_INET6:
1099 ac = is_nat_v6 (&((const struct sockaddr_in6 *) addr)->sin6_addr) 1170 ac = is_nat_v6 (&((const struct sockaddr_in6 *) addr)->sin6_addr)
1100 ? GNUNET_NAT_AC_LAN_PRIVATE 1171 ? GNUNET_NAT_AC_LAN_PRIVATE
1101 : GNUNET_NAT_AC_GLOBAL_EXTERN; 1172 : GNUNET_NAT_AC_EXTERN;
1102 break; 1173 break;
1103 default: 1174 default:
1104 GNUNET_break (0); 1175 GNUNET_break (0);
1105 return; 1176 return;
1106 } 1177 }
1178 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1179 "upnp external address %s: %s\n",
1180 add_remove ? "added" : "removed",
1181 GNUNET_a2s (addr,
1182 addrlen));
1107 notify_client (ac, 1183 notify_client (ac,
1108 ch, 1184 ch,
1109 add_remove, 1185 add_remove,
@@ -1291,7 +1367,7 @@ notify_clients_stun_change (const struct sockaddr_in *ip,
1291 sizeof (v4), 1367 sizeof (v4),
1292 GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE); 1368 GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE);
1293 msg->add_remove = htonl ((int32_t) add); 1369 msg->add_remove = htonl ((int32_t) add);
1294 msg->addr_class = htonl (GNUNET_NAT_AC_GLOBAL_EXTERN | 1370 msg->addr_class = htonl (GNUNET_NAT_AC_EXTERN |
1295 GNUNET_NAT_AC_GLOBAL); 1371 GNUNET_NAT_AC_GLOBAL);
1296 GNUNET_memcpy (&msg[1], 1372 GNUNET_memcpy (&msg[1],
1297 &v4, 1373 &v4,