diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/gnunet_nat_service.h | 8 | ||||
-rw-r--r-- | src/nat/gnunet-service-nat.c | 86 |
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, |