aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/gnunet_nat_service.h25
-rw-r--r--src/nat/gnunet-service-nat.c94
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 */
614static int
615match_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 */
638static int
639match_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);