Support variety of IPv6 addresses on RDNS-on-cache

IPv6 address has multiple representation formats. The following
addresses are the same:

  "2001:db8::102:304"
  "2001:0db8:0000:0000:0000:0000:0102:0304"
  "2001:db8::1.2.3.4"

In original design, the RDNS-on-cache can only match IPv6 address with
format "2001:db8::102:304", but not with the others. It is because all
different representations are converted to a single binary form while
they are stored in cache. And of course, it will be a single format if
the cached IP address is converted back to text form while doing text
comparison. In this commit, the RDNS-on-cache converts query address to
binary form and binary compares with cached entry, rather than text
comparison. Also, add two test cases.

Bug: 131051938
Test: atest resolv_cache_unit_test.cpp#GetHostByAddrFromCache_InvalidArgs
      atest resolv_cache_unit_test.cpp#GetHostByAddrFromCache
Change-Id: I064f4bafca91ad7dbbd9b37ce3c2d05f8d6b954d
diff --git a/resolv_cache_unit_test.cpp b/resolv_cache_unit_test.cpp
index 1db209f..22e61c0 100644
--- a/resolv_cache_unit_test.cpp
+++ b/resolv_cache_unit_test.cpp
@@ -716,6 +716,85 @@
     expectCacheStats("GetStats", TEST_NETID, cacheStats);
 }
 
+TEST_F(ResolvCacheTest, GetHostByAddrFromCache_InvalidArgs) {
+    char domain_name[NS_MAXDNAME] = {};
+    const char query_v4[] = "1.2.3.5";
+
+    // invalid buffer size
+    EXPECT_FALSE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME + 1, nullptr,
+                                                 AF_INET));
+    EXPECT_STREQ("", domain_name);
+
+    // invalid query
+    EXPECT_FALSE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME, nullptr,
+                                                 AF_INET));
+    EXPECT_STREQ("", domain_name);
+
+    // unsupported AF
+    EXPECT_FALSE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME, query_v4,
+                                                 AF_UNSPEC));
+    EXPECT_STREQ("", domain_name);
+}
+
+TEST_F(ResolvCacheTest, GetHostByAddrFromCache) {
+    char domain_name[NS_MAXDNAME] = {};
+    const char query_v4[] = "1.2.3.5";
+    const char query_v6[] = "2001:db8::102:304";
+    const char query_v6_unabbreviated[] = "2001:0db8:0000:0000:0000:0000:0102:0304";
+    const char query_v6_mixed[] = "2001:db8::1.2.3.4";
+    const char answer[] = "existent.in.cache";
+
+    // cache does not exist
+    EXPECT_FALSE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME, query_v4,
+                                                 AF_INET));
+    EXPECT_STREQ("", domain_name);
+
+    // cache is empty
+    EXPECT_EQ(0, cacheCreate(TEST_NETID));
+    EXPECT_FALSE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME, query_v4,
+                                                 AF_INET));
+    EXPECT_STREQ("", domain_name);
+
+    // no v4 match in cache
+    CacheEntry ce = makeCacheEntry(QUERY, "any.data", ns_c_in, ns_t_a, "1.2.3.4");
+    EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
+    EXPECT_FALSE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME, query_v4,
+                                                 AF_INET));
+    EXPECT_STREQ("", domain_name);
+
+    // v4 match
+    ce = makeCacheEntry(QUERY, answer, ns_c_in, ns_t_a, query_v4);
+    EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
+    EXPECT_TRUE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME, query_v4,
+                                                AF_INET));
+    EXPECT_STREQ(answer, domain_name);
+
+    // no v6 match in cache
+    memset(domain_name, 0, NS_MAXDNAME);
+    EXPECT_FALSE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME, query_v6,
+                                                 AF_INET6));
+    EXPECT_STREQ("", domain_name);
+
+    // v6 match
+    ce = makeCacheEntry(QUERY, answer, ns_c_in, ns_t_aaaa, query_v6);
+    EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
+    EXPECT_TRUE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME, query_v6,
+                                                AF_INET6));
+    EXPECT_STREQ(answer, domain_name);
+
+    // v6 match with unabbreviated address format
+    memset(domain_name, 0, NS_MAXDNAME);
+    EXPECT_TRUE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME,
+                                                query_v6_unabbreviated, AF_INET6));
+    EXPECT_STREQ(answer, domain_name);
+
+    // v6 with mixed address format
+    memset(domain_name, 0, NS_MAXDNAME);
+    EXPECT_TRUE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME,
+                                                query_v6_mixed, AF_INET6));
+    EXPECT_STREQ(answer, domain_name);
+}
+
 namespace {
 
 constexpr int EAI_OK = 0;