diff options
author | Christian Grothoff <christian@grothoff.org> | 2016-11-27 23:43:46 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2016-11-27 23:43:46 +0100 |
commit | 6aa3cedfa5e9df7aacbbdcf62c977e09b0e7f6c3 (patch) | |
tree | ebee5364f86de1fb9e6665ed46cb12a167b449ad /src/nat | |
parent | efa2e98f9b1231a76c023c0d67540da066b51742 (diff) | |
download | gnunet-6aa3cedfa5e9df7aacbbdcf62c977e09b0e7f6c3.tar.gz gnunet-6aa3cedfa5e9df7aacbbdcf62c977e09b0e7f6c3.zip |
expand logic for address class detection, including private and sensitive IP classification
Diffstat (limited to 'src/nat')
-rw-r--r-- | src/nat/gnunet-service-nat.c | 94 |
1 files changed, 94 insertions, 0 deletions
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); |