/* Is IP a local ip or not. */ bool ip_is_local(IP ip) { if (ip.family == TOX_AF_INET) { IP4 ip4 = ip.ip.v4; /* Loopback. */ if (ip4.uint8[0] == 127) { return 1; } } else { /* embedded IPv4-in-IPv6 */ if (IPV6_IPV4_IN_V6(ip.ip.v6)) { IP ip4; ip4.family = TOX_AF_INET; ip4.ip.v4.uint32 = ip.ip.v6.uint32[3]; return ip_is_local(ip4); } /* localhost in IPv6 (::1) */ if (ip.ip.v6.uint64[0] == 0 && ip.ip.v6.uint32[2] == 0 && ip.ip.v6.uint32[3] == net_htonl(1)) { return 1; } } return 0; }
/* Is IP a local ip or not. */ bool Local_ip(IP ip) { if (ip.family == AF_INET) { IP4 ip4 = ip.ip4; /* Loopback. */ if (ip4.uint8[0] == 127) { return 1; } } else { /* embedded IPv4-in-IPv6 */ if (IPV6_IPV4_IN_V6(ip.ip6)) { IP ip4; ip4.family = AF_INET; ip4.ip4.uint32 = ip.ip6.uint32[3]; return Local_ip(ip4); } /* localhost in IPv6 (::1) */ if (ip.ip6.uint64[0] == 0 && ip.ip6.uint32[2] == 0 && ip.ip6.uint32[3] == htonl(1)) { return 1; } } return 0; }
END_TEST START_TEST(test_ip_equal) { int res; IP ip1, ip2; ip_reset(&ip1); ip_reset(&ip2); res = ip_equal(NULL, NULL); ck_assert_msg(res == 0, "ip_equal(NULL, NULL): expected result 0, got %u.", res); res = ip_equal(&ip1, NULL); ck_assert_msg(res == 0, "ip_equal(PTR, NULL): expected result 0, got %u.", res); res = ip_equal(NULL, &ip1); ck_assert_msg(res == 0, "ip_equal(NULL, PTR): expected result 0, got %u.", res); ip1.family = AF_INET; ip1.ip4.uint32 = net_htonl(0x7F000001); res = ip_equal(&ip1, &ip2); ck_assert_msg(res == 0, "ip_equal( {AF_INET, 127.0.0.1}, {AF_UNSPEC, 0} ): expected result 0, got %u.", res); ip2.family = AF_INET; ip2.ip4.uint32 = net_htonl(0x7F000001); res = ip_equal(&ip1, &ip2); ck_assert_msg(res != 0, "ip_equal( {AF_INET, 127.0.0.1}, {AF_INET, 127.0.0.1} ): expected result != 0, got 0."); ip2.ip4.uint32 = net_htonl(0x7F000002); res = ip_equal(&ip1, &ip2); ck_assert_msg(res == 0, "ip_equal( {AF_INET, 127.0.0.1}, {AF_INET, 127.0.0.2} ): expected result 0, got %u.", res); ip2.family = AF_INET6; ip2.ip6.uint32[0] = 0; ip2.ip6.uint32[1] = 0; ip2.ip6.uint32[2] = net_htonl(0xFFFF); ip2.ip6.uint32[3] = net_htonl(0x7F000001); ck_assert_msg(IPV6_IPV4_IN_V6(ip2.ip6) != 0, "IPV6_IPV4_IN_V6(::ffff:127.0.0.1): expected != 0, got 0."); res = ip_equal(&ip1, &ip2); ck_assert_msg(res != 0, "ip_equal( {AF_INET, 127.0.0.1}, {AF_INET6, ::ffff:127.0.0.1} ): expected result != 0, got 0."); memcpy(&ip2.ip6, &in6addr_loopback, sizeof(IP6)); res = ip_equal(&ip1, &ip2); ck_assert_msg(res == 0, "ip_equal( {AF_INET, 127.0.0.1}, {AF_INET6, ::1} ): expected result 0, got %u.", res); memcpy(&ip1, &ip2, sizeof(IP)); res = ip_equal(&ip1, &ip2); ck_assert_msg(res != 0, "ip_equal( {AF_INET6, ::1}, {AF_INET6, ::1} ): expected result != 0, got 0."); ip2.ip6.uint8[15]++; res = ip_equal(&ip1, &ip2); ck_assert_msg(res == 0, "ip_equal( {AF_INET6, ::1}, {AF_INET6, ::2} ): expected result 0, got %res.", res); }
/* return 0 if ip is a LAN ip. * return -1 if it is not. */ int ip_is_lan(IP ip) { if (ip_is_local(ip)) { return 0; } if (ip.family == TOX_AF_INET) { IP4 ip4 = ip.ip.v4; /* 10.0.0.0 to 10.255.255.255 range. */ if (ip4.uint8[0] == 10) { return 0; } /* 172.16.0.0 to 172.31.255.255 range. */ if (ip4.uint8[0] == 172 && ip4.uint8[1] >= 16 && ip4.uint8[1] <= 31) { return 0; } /* 192.168.0.0 to 192.168.255.255 range. */ if (ip4.uint8[0] == 192 && ip4.uint8[1] == 168) { return 0; } /* 169.254.1.0 to 169.254.254.255 range. */ if (ip4.uint8[0] == 169 && ip4.uint8[1] == 254 && ip4.uint8[2] != 0 && ip4.uint8[2] != 255) { return 0; } /* RFC 6598: 100.64.0.0 to 100.127.255.255 (100.64.0.0/10) * (shared address space to stack another layer of NAT) */ if ((ip4.uint8[0] == 100) && ((ip4.uint8[1] & 0xC0) == 0x40)) { return 0; } } else if (ip.family == TOX_AF_INET6) { /* autogenerated for each interface: FE80::* (up to FEBF::*) FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */ if (((ip.ip.v6.uint8[0] == 0xFF) && (ip.ip.v6.uint8[1] < 3) && (ip.ip.v6.uint8[15] == 1)) || ((ip.ip.v6.uint8[0] == 0xFE) && ((ip.ip.v6.uint8[1] & 0xC0) == 0x80))) { return 0; } /* embedded IPv4-in-IPv6 */ if (IPV6_IPV4_IN_V6(ip.ip.v6)) { IP ip4; ip4.family = TOX_AF_INET; ip4.ip.v4.uint32 = ip.ip.v6.uint32[3]; return ip_is_lan(ip4); } } return -1; }