diff options
-rw-r--r-- | src/include/gnunet_nat_service.h | 25 | ||||
-rw-r--r-- | src/nat/gnunet-service-nat.c | 94 |
2 files changed, 115 insertions, 4 deletions
diff --git a/src/include/gnunet_nat_service.h b/src/include/gnunet_nat_service.h index ad3438538..a59069545 100644 --- a/src/include/gnunet_nat_service.h +++ b/src/include/gnunet_nat_service.h | |||
@@ -64,16 +64,21 @@ enum GNUNET_NAT_AddressClass | |||
64 | GNUNET_NAT_AC_OTHER = 1, | 64 | GNUNET_NAT_AC_OTHER = 1, |
65 | 65 | ||
66 | /** | 66 | /** |
67 | * Addresses that are global and are insensitive | 67 | * Addresses that are highly sensitive |
68 | * (i.e. IPv4). | 68 | * (i.e. IPv6 with our MAC). |
69 | */ | ||
70 | GNUNET_NAT_AC_PRIVATE = 2, | ||
71 | |||
72 | /** | ||
73 | * Addresses that are global (i.e. IPv4). | ||
69 | */ | 74 | */ |
70 | GNUNET_NAT_AC_GLOBAL = 2, | 75 | GNUNET_NAT_AC_GLOBAL = 4, |
71 | 76 | ||
72 | /** | 77 | /** |
73 | * Addresses that are global and are sensitive | 78 | * Addresses that are global and are sensitive |
74 | * (i.e. IPv6 with our MAC). | 79 | * (i.e. IPv6 with our MAC). |
75 | */ | 80 | */ |
76 | GNUNET_NAT_AC_GLOBAL_PRIVATE = 4, | 81 | GNUNET_NAT_AC_GLOBAL_PRIVATE = 6, |
77 | 82 | ||
78 | /** | 83 | /** |
79 | * Addresses useful in the local wired network, | 84 | * Addresses useful in the local wired network, |
@@ -81,6 +86,13 @@ enum GNUNET_NAT_AddressClass | |||
81 | * Useful for broadcasts. | 86 | * Useful for broadcasts. |
82 | */ | 87 | */ |
83 | GNUNET_NAT_AC_LAN = 8, | 88 | GNUNET_NAT_AC_LAN = 8, |
89 | |||
90 | /** | ||
91 | * Addresses useful in the local wired network, | ||
92 | * i.e. a MAC. Sensitive, but obvious to people nearby. | ||
93 | * Useful for broadcasts. | ||
94 | */ | ||
95 | GNUNET_NAT_AC_LAN_PRIVATE = 10, | ||
84 | 96 | ||
85 | /** | 97 | /** |
86 | * Addresses useful in the local wireless network, | 98 | * Addresses useful in the local wireless network, |
@@ -96,6 +108,11 @@ enum GNUNET_NAT_AddressClass | |||
96 | GNUNET_NAT_AC_BT = 32, | 108 | GNUNET_NAT_AC_BT = 32, |
97 | 109 | ||
98 | /** | 110 | /** |
111 | * Loopback addresses, only useful under special cirumstances. | ||
112 | */ | ||
113 | GNUNET_NAT_AC_LOOPBACK = 64, | ||
114 | |||
115 | /** | ||
99 | * Bitmask for "any" address. | 116 | * Bitmask for "any" address. |
100 | */ | 117 | */ |
101 | GNUNET_NAT_AC_ANY = 65535 | 118 | GNUNET_NAT_AC_ANY = 65535 |
diff --git a/src/nat/gnunet-service-nat.c b/src/nat/gnunet-service-nat.c index e42a94ea4..a6aa21cd1 100644 --- a/src/nat/gnunet-service-nat.c +++ b/src/nat/gnunet-service-nat.c | |||
@@ -604,6 +604,72 @@ struct IfcProcContext | |||
604 | 604 | ||
605 | 605 | ||
606 | /** | 606 | /** |
607 | * Check if @a ip is in @a network with @a bits netmask. | ||
608 | * | ||
609 | * @param network to test | ||
610 | * @param ip IP address to test | ||
611 | * @param bits bitmask for the network | ||
612 | * @return #GNUNET_YES if @a ip is in @a network | ||
613 | */ | ||
614 | static int | ||
615 | match_ipv4 (const char *network, | ||
616 | const struct in_addr *ip, | ||
617 | uint8_t bits) | ||
618 | { | ||
619 | struct in_addr net; | ||
620 | |||
621 | if (0 == bits) | ||
622 | return GNUNET_YES; | ||
623 | GNUNET_assert (1 == inet_pton (AF_INET, | ||
624 | network, | ||
625 | &net)); | ||
626 | return ! ((ip->s_addr ^ net.s_addr) & htonl (0xFFFFFFFFu << (32 - bits))); | ||
627 | } | ||
628 | |||
629 | |||
630 | /** | ||
631 | * Check if @a ip is in @a network with @a bits netmask. | ||
632 | * | ||
633 | * @param network to test | ||
634 | * @param ip IP address to test | ||
635 | * @param bits bitmask for the network | ||
636 | * @return #GNUNET_YES if @a ip is in @a network | ||
637 | */ | ||
638 | static int | ||
639 | match_ipv6 (const char *network, | ||
640 | const struct in6_addr *ip, | ||
641 | uint8_t bits) | ||
642 | { | ||
643 | struct in6_addr net; | ||
644 | struct in6_addr mask; | ||
645 | unsigned int off; | ||
646 | |||
647 | if (0 == bits) | ||
648 | return GNUNET_YES; | ||
649 | GNUNET_assert (1 == inet_pton (AF_INET, | ||
650 | network, | ||
651 | &net)); | ||
652 | memset (&mask, 0, sizeof (mask)); | ||
653 | off = 0; | ||
654 | while (bits > 8) | ||
655 | { | ||
656 | mask.s6_addr[off++] = 0xFF; | ||
657 | bits -= 8; | ||
658 | } | ||
659 | while (bits > 0) | ||
660 | { | ||
661 | mask.s6_addr[off] = (mask.s6_addr[off] >> 1) + 0x80; | ||
662 | bits--; | ||
663 | } | ||
664 | for (unsigned j = 0; j < sizeof (struct in6_addr) / sizeof (uint32_t); j++) | ||
665 | if (((((uint32_t *) ip)[j] & ((uint32_t *) &mask)[j])) != | ||
666 | (((uint32_t *) &net)[j] & ((int *) &mask)[j])) | ||
667 | return GNUNET_NO; | ||
668 | return GNUNET_YES; | ||
669 | } | ||
670 | |||
671 | |||
672 | /** | ||
607 | * Callback function invoked for each interface found. Adds them | 673 | * Callback function invoked for each interface found. Adds them |
608 | * to our new address list. | 674 | * to our new address list. |
609 | * | 675 | * |
@@ -629,16 +695,43 @@ ifc_proc (void *cls, | |||
629 | struct LocalAddressList *lal; | 695 | struct LocalAddressList *lal; |
630 | size_t alen; | 696 | size_t alen; |
631 | const void *ip; | 697 | const void *ip; |
698 | const struct in6_addr *v6; | ||
699 | enum GNUNET_NAT_AddressClass ac; | ||
632 | 700 | ||
633 | switch (addr->sa_family) | 701 | switch (addr->sa_family) |
634 | { | 702 | { |
635 | case AF_INET: | 703 | case AF_INET: |
636 | alen = sizeof (struct in_addr); | 704 | alen = sizeof (struct in_addr); |
637 | ip = &((const struct sockaddr_in *) addr)->sin_addr; | 705 | ip = &((const struct sockaddr_in *) addr)->sin_addr; |
706 | if (match_ipv4 ("127.0.0.0", ip, 8)) | ||
707 | ac = GNUNET_NAT_AC_LOOPBACK; | ||
708 | else if (match_ipv4 ("10.0.0.0", ip, 8) || /* RFC 1918 */ | ||
709 | match_ipv4 ("100.64.0.0", ip, 10) || /* CG-NAT, RFC 6598 */ | ||
710 | match_ipv4 ("192.168.0.0", ip, 12) || /* RFC 1918 */ | ||
711 | match_ipv4 ("169.254.0.0", ip, 16) || /* AUTO, RFC 3927 */ | ||
712 | match_ipv4 ("172.16.0.0", ip, 16)) /* RFC 1918 */ | ||
713 | ac = GNUNET_NAT_AC_LAN; | ||
714 | else | ||
715 | ac = GNUNET_NAT_AC_GLOBAL; | ||
638 | break; | 716 | break; |
639 | case AF_INET6: | 717 | case AF_INET6: |
640 | alen = sizeof (struct in6_addr); | 718 | alen = sizeof (struct in6_addr); |
641 | ip = &((const struct sockaddr_in6 *) addr)->sin6_addr; | 719 | ip = &((const struct sockaddr_in6 *) addr)->sin6_addr; |
720 | if (match_ipv6 ("::1", ip, 128)) | ||
721 | ac = GNUNET_NAT_AC_LOOPBACK; | ||
722 | else if (match_ipv6 ("fc00::", ip, 7) || /* RFC 4193 */ | ||
723 | match_ipv6 ("fec0::", ip, 10) || /* RFC 3879 */ | ||
724 | match_ipv6 ("fe80::", ip, 10)) /* RFC 4291, link-local */ | ||
725 | ac = GNUNET_NAT_AC_LAN; | ||
726 | else | ||
727 | ac = GNUNET_NAT_AC_GLOBAL; | ||
728 | v6 = ip; | ||
729 | if ( (v6->s6_addr[11] == 0xFF) && | ||
730 | (v6->s6_addr[12] == 0xFE) ) | ||
731 | { | ||
732 | /* contains a MAC, be extra careful! */ | ||
733 | ac |= GNUNET_NAT_AC_PRIVATE; | ||
734 | } | ||
642 | break; | 735 | break; |
643 | #if AF_UNIX | 736 | #if AF_UNIX |
644 | case AF_UNIX: | 737 | case AF_UNIX: |
@@ -652,6 +745,7 @@ ifc_proc (void *cls, | |||
652 | lal = GNUNET_malloc (sizeof (*lal) + alen); | 745 | lal = GNUNET_malloc (sizeof (*lal) + alen); |
653 | lal->af = addr->sa_family; | 746 | lal->af = addr->sa_family; |
654 | lal->addr = &lal[1]; | 747 | lal->addr = &lal[1]; |
748 | lal->ac = ac; | ||
655 | GNUNET_memcpy (&lal[1], | 749 | GNUNET_memcpy (&lal[1], |
656 | ip, | 750 | ip, |
657 | alen); | 751 | alen); |