aboutsummaryrefslogtreecommitdiff
path: root/src/nat/gnunet-service-nat.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-11-30 06:26:53 +0100
committerChristian Grothoff <christian@grothoff.org>2016-11-30 06:26:53 +0100
commit27068700bceca89cd940816a7b5cd03933d3cc0b (patch)
tree59fbeccc7b1e8d8358b8cb1492bdb5043734e750 /src/nat/gnunet-service-nat.c
parent948983f991c6fa623cf008826b62a6142dafa189 (diff)
downloadgnunet-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.c143
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 */
676static int
677is_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 */
695static int
696is_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 */
793static void
794notify_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