diff options
author | Christian Grothoff <christian@grothoff.org> | 2016-11-30 06:26:53 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2016-11-30 06:26:53 +0100 |
commit | 27068700bceca89cd940816a7b5cd03933d3cc0b (patch) | |
tree | 59fbeccc7b1e8d8358b8cb1492bdb5043734e750 /src/nat/gnunet-service-nat.c | |
parent | 948983f991c6fa623cf008826b62a6142dafa189 (diff) | |
download | gnunet-27068700bceca89cd940816a7b5cd03933d3cc0b.tar.gz gnunet-27068700bceca89cd940816a7b5cd03933d3cc0b.zip |
handle ports for interface scan data properly
Diffstat (limited to 'src/nat/gnunet-service-nat.c')
-rw-r--r-- | src/nat/gnunet-service-nat.c | 143 |
1 files changed, 111 insertions, 32 deletions
diff --git a/src/nat/gnunet-service-nat.c b/src/nat/gnunet-service-nat.c index 548cf1c36..f7dbbce3a 100644 --- a/src/nat/gnunet-service-nat.c +++ b/src/nat/gnunet-service-nat.c | |||
@@ -134,8 +134,6 @@ struct LocalAddressList | |||
134 | }; | 134 | }; |
135 | 135 | ||
136 | 136 | ||
137 | |||
138 | |||
139 | /** | 137 | /** |
140 | * Handle to our current configuration. | 138 | * Handle to our current configuration. |
141 | */ | 139 | */ |
@@ -669,6 +667,42 @@ match_ipv6 (const char *network, | |||
669 | 667 | ||
670 | 668 | ||
671 | /** | 669 | /** |
670 | * Test if the given IPv4 address is in a known range | ||
671 | * for private networks. | ||
672 | * | ||
673 | * @param ip address to test | ||
674 | * @return #GNUNET_YES if @a ip is in a NAT range | ||
675 | */ | ||
676 | static int | ||
677 | is_nat_v4 (const struct in_addr *ip) | ||
678 | { | ||
679 | return | ||
680 | match_ipv4 ("10.0.0.0", ip, 8) || /* RFC 1918 */ | ||
681 | match_ipv4 ("100.64.0.0", ip, 10) || /* CG-NAT, RFC 6598 */ | ||
682 | match_ipv4 ("192.168.0.0", ip, 12) || /* RFC 1918 */ | ||
683 | match_ipv4 ("169.254.0.0", ip, 16) || /* AUTO, RFC 3927 */ | ||
684 | match_ipv4 ("172.16.0.0", ip, 16); /* RFC 1918 */ | ||
685 | } | ||
686 | |||
687 | |||
688 | /** | ||
689 | * Test if the given IPv6 address is in a known range | ||
690 | * for private networks. | ||
691 | * | ||
692 | * @param ip address to test | ||
693 | * @return #GNUNET_YES if @a ip is in a NAT range | ||
694 | */ | ||
695 | static int | ||
696 | is_nat_v6 (const struct in6_addr *ip) | ||
697 | { | ||
698 | return | ||
699 | match_ipv6 ("fc00::", ip, 7) || /* RFC 4193 */ | ||
700 | match_ipv6 ("fec0::", ip, 10) || /* RFC 3879 */ | ||
701 | match_ipv6 ("fe80::", ip, 10); /* RFC 4291, link-local */ | ||
702 | } | ||
703 | |||
704 | |||
705 | /** | ||
672 | * Callback function invoked for each interface found. Adds them | 706 | * Callback function invoked for each interface found. Adds them |
673 | * to our new address list. | 707 | * to our new address list. |
674 | * | 708 | * |
@@ -693,40 +727,33 @@ ifc_proc (void *cls, | |||
693 | struct IfcProcContext *ifc_ctx = cls; | 727 | struct IfcProcContext *ifc_ctx = cls; |
694 | struct LocalAddressList *lal; | 728 | struct LocalAddressList *lal; |
695 | size_t alen; | 729 | size_t alen; |
696 | const void *ip; | 730 | const struct in_addr *ip4; |
697 | const struct in6_addr *v6; | 731 | const struct in6_addr *ip6; |
698 | enum GNUNET_NAT_AddressClass ac; | 732 | enum GNUNET_NAT_AddressClass ac; |
699 | 733 | ||
700 | switch (addr->sa_family) | 734 | switch (addr->sa_family) |
701 | { | 735 | { |
702 | case AF_INET: | 736 | case AF_INET: |
703 | alen = sizeof (struct sockaddr_in); | 737 | alen = sizeof (struct sockaddr_in); |
704 | ip = &((const struct sockaddr_in *) addr)->sin_addr; | 738 | ip4 = &((const struct sockaddr_in *) addr)->sin_addr; |
705 | if (match_ipv4 ("127.0.0.0", ip, 8)) | 739 | if (match_ipv4 ("127.0.0.0", ip4, 8)) |
706 | ac = GNUNET_NAT_AC_LOOPBACK; | 740 | ac = GNUNET_NAT_AC_LOOPBACK; |
707 | else if (match_ipv4 ("10.0.0.0", ip, 8) || /* RFC 1918 */ | 741 | else if (is_nat_v4 (ip4)) |
708 | match_ipv4 ("100.64.0.0", ip, 10) || /* CG-NAT, RFC 6598 */ | ||
709 | match_ipv4 ("192.168.0.0", ip, 12) || /* RFC 1918 */ | ||
710 | match_ipv4 ("169.254.0.0", ip, 16) || /* AUTO, RFC 3927 */ | ||
711 | match_ipv4 ("172.16.0.0", ip, 16)) /* RFC 1918 */ | ||
712 | ac = GNUNET_NAT_AC_LAN; | 742 | ac = GNUNET_NAT_AC_LAN; |
713 | else | 743 | else |
714 | ac = GNUNET_NAT_AC_GLOBAL; | 744 | ac = GNUNET_NAT_AC_GLOBAL; |
715 | break; | 745 | break; |
716 | case AF_INET6: | 746 | case AF_INET6: |
717 | alen = sizeof (struct sockaddr_in6); | 747 | alen = sizeof (struct sockaddr_in6); |
718 | ip = &((const struct sockaddr_in6 *) addr)->sin6_addr; | 748 | ip6 = &((const struct sockaddr_in6 *) addr)->sin6_addr; |
719 | if (match_ipv6 ("::1", ip, 128)) | 749 | if (match_ipv6 ("::1", ip6, 128)) |
720 | ac = GNUNET_NAT_AC_LOOPBACK; | 750 | ac = GNUNET_NAT_AC_LOOPBACK; |
721 | else if (match_ipv6 ("fc00::", ip, 7) || /* RFC 4193 */ | 751 | else if (is_nat_v6 (ip6)) |
722 | match_ipv6 ("fec0::", ip, 10) || /* RFC 3879 */ | ||
723 | match_ipv6 ("fe80::", ip, 10)) /* RFC 4291, link-local */ | ||
724 | ac = GNUNET_NAT_AC_LAN; | 752 | ac = GNUNET_NAT_AC_LAN; |
725 | else | 753 | else |
726 | ac = GNUNET_NAT_AC_GLOBAL; | 754 | ac = GNUNET_NAT_AC_GLOBAL; |
727 | v6 = ip; | 755 | if ( (ip6->s6_addr[11] == 0xFF) && |
728 | if ( (v6->s6_addr[11] == 0xFF) && | 756 | (ip6->s6_addr[12] == 0xFE) ) |
729 | (v6->s6_addr[12] == 0xFE) ) | ||
730 | { | 757 | { |
731 | /* contains a MAC, be extra careful! */ | 758 | /* contains a MAC, be extra careful! */ |
732 | ac |= GNUNET_NAT_AC_PRIVATE; | 759 | ac |= GNUNET_NAT_AC_PRIVATE; |
@@ -755,6 +782,37 @@ ifc_proc (void *cls, | |||
755 | 782 | ||
756 | 783 | ||
757 | /** | 784 | /** |
785 | * Notify client about a change in the list | ||
786 | * of addresses this peer has. | ||
787 | * | ||
788 | * @param delta the entry in the list that changed | ||
789 | * @param add #GNUNET_YES to add, #GNUNET_NO to remove | ||
790 | * @param addr the address that changed | ||
791 | * @param addr_len number of bytes in @a addr | ||
792 | */ | ||
793 | static void | ||
794 | notify_client (struct LocalAddressList *delta, | ||
795 | int add, | ||
796 | const void *addr, | ||
797 | size_t addr_len) | ||
798 | { | ||
799 | struct GNUNET_MQ_Envelope *env; | ||
800 | struct GNUNET_NAT_AddressChangeNotificationMessage *msg; | ||
801 | |||
802 | env = GNUNET_MQ_msg_extra (msg, | ||
803 | alen, | ||
804 | GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE); | ||
805 | msg->add_remove = htonl (add); | ||
806 | msg->addr_class = htonl (delta->ac); | ||
807 | GNUNET_memcpy (&msg[1], | ||
808 | addr, | ||
809 | alen); | ||
810 | GNUNET_MQ_send (ch->mq, | ||
811 | env); | ||
812 | } | ||
813 | |||
814 | |||
815 | /** | ||
758 | * Notify all clients about a change in the list | 816 | * Notify all clients about a change in the list |
759 | * of addresses this peer has. | 817 | * of addresses this peer has. |
760 | * | 818 | * |
@@ -769,9 +827,9 @@ notify_clients (struct LocalAddressList *delta, | |||
769 | NULL != ch; | 827 | NULL != ch; |
770 | ch = ch->next) | 828 | ch = ch->next) |
771 | { | 829 | { |
772 | struct GNUNET_MQ_Envelope *env; | ||
773 | struct GNUNET_NAT_AddressChangeNotificationMessage *msg; | ||
774 | size_t alen; | 830 | size_t alen; |
831 | struct sockaddr_in v4; | ||
832 | struct sockaddr_in6 v6; | ||
775 | 833 | ||
776 | if (0 == (ch->flags & GNUNET_NAT_RF_ADDRESSES)) | 834 | if (0 == (ch->flags & GNUNET_NAT_RF_ADDRESSES)) |
777 | continue; | 835 | continue; |
@@ -779,25 +837,46 @@ notify_clients (struct LocalAddressList *delta, | |||
779 | { | 837 | { |
780 | case AF_INET: | 838 | case AF_INET: |
781 | alen = sizeof (struct sockaddr_in); | 839 | alen = sizeof (struct sockaddr_in); |
840 | GNUNET_memcpy (&v4, | ||
841 | &delta->addr, | ||
842 | alen); | ||
843 | for (unsigned int i=0;i<ch->num_addrs;i++) | ||
844 | { | ||
845 | const struct sockaddr_in *c4; | ||
846 | |||
847 | if (AF_INET != ch->addrs[i]->sa_family) | ||
848 | continue; /* IPv4 not relevant */ | ||
849 | c4 = (const struct sockaddr_in *) ch->addrs[i]; | ||
850 | v4.sin_port = c4->sin_port; | ||
851 | notify_client (delta, | ||
852 | add, | ||
853 | &v4, | ||
854 | alen); | ||
855 | } | ||
782 | break; | 856 | break; |
783 | case AF_INET6: | 857 | case AF_INET6: |
784 | alen = sizeof (struct sockaddr_in6); | 858 | alen = sizeof (struct sockaddr_in6); |
859 | GNUNET_memcpy (&v6, | ||
860 | &delta->addr, | ||
861 | alen); | ||
862 | for (unsigned int i=0;i<ch->num_addrs;i++) | ||
863 | { | ||
864 | const struct sockaddr_in6 *c6; | ||
865 | |||
866 | if (AF_INET6 != ch->addrs[i]->sa_family) | ||
867 | continue; /* IPv4 not relevant */ | ||
868 | c6 = (const struct sockaddr_in6 *) ch->addrs[i]; | ||
869 | v6.sin_port = c6->sin_port; | ||
870 | notify_client (delta, | ||
871 | add, | ||
872 | &v6, | ||
873 | alen); | ||
874 | } | ||
785 | break; | 875 | break; |
786 | default: | 876 | default: |
787 | GNUNET_break (0); | 877 | GNUNET_break (0); |
788 | continue; | 878 | continue; |
789 | } | 879 | } |
790 | env = GNUNET_MQ_msg_extra (msg, | ||
791 | alen, | ||
792 | GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE); | ||
793 | msg->add_remove = htonl (add); | ||
794 | msg->addr_class = htonl (delta->ac); | ||
795 | GNUNET_memcpy (&msg[1], | ||
796 | &delta->addr, | ||
797 | alen); | ||
798 | /* FIXME: what about the port number? */ | ||
799 | GNUNET_MQ_send (ch->mq, | ||
800 | env); | ||
801 | } | 880 | } |
802 | } | 881 | } |
803 | 882 | ||