Map clat devices to cellular on Android

Bug: webrtc:10346
Change-Id: I566a1ce4dc5a89152421a39c97b2f2717d525222
Reviewed-on: https://webrtc-review.googlesource.com/c/123661
Reviewed-by: Qingsi Wang <qingsi@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Jeroen de Borst <jeroendb@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26822}
diff --git a/rtc_base/network.cc b/rtc_base/network.cc
index 496c769..9c9bc57 100644
--- a/rtc_base/network.cc
+++ b/rtc_base/network.cc
@@ -235,7 +235,8 @@
   if (MatchTypeNameWithIndexPattern(network_name, "rmnet") ||
       MatchTypeNameWithIndexPattern(network_name, "rmnet_data") ||
       MatchTypeNameWithIndexPattern(network_name, "v4-rmnet") ||
-      MatchTypeNameWithIndexPattern(network_name, "v4-rmnet_data")) {
+      MatchTypeNameWithIndexPattern(network_name, "v4-rmnet_data") ||
+      MatchTypeNameWithIndexPattern(network_name, "clat")) {
     return ADAPTER_TYPE_CELLULAR;
   }
   if (MatchTypeNameWithIndexPattern(network_name, "wlan")) {
@@ -703,7 +704,9 @@
 
             break;
           }
-          default: { continue; }
+          default: {
+            continue;
+          }
         }
 
         IPAddress prefix;
diff --git a/rtc_base/network_unittest.cc b/rtc_base/network_unittest.cc
index a98d393..1ba573e 100644
--- a/rtc_base/network_unittest.cc
+++ b/rtc_base/network_unittest.cc
@@ -179,6 +179,48 @@
     return addr_list;
   }
 
+  struct sockaddr_in* CreateIpv4Addr(const std::string& ip_string) {
+    struct sockaddr_in* ipv4_addr =
+        static_cast<struct sockaddr_in*>(malloc(sizeof(struct sockaddr_in)));
+    memset(ipv4_addr, 0, sizeof(struct sockaddr_in));
+    ipv4_addr->sin_family = AF_INET;
+    IPAddress ip;
+    IPFromString(ip_string, &ip);
+    ipv4_addr->sin_addr = ip.ipv4_address();
+    return ipv4_addr;
+  }
+
+  // Pointers created here need to be released via ReleaseIfAddrs.
+  struct ifaddrs* AddIpv4Address(struct ifaddrs* list,
+                                 char* if_name,
+                                 const std::string& ipv4_address,
+                                 const std::string& ipv4_netmask) {
+    struct ifaddrs* if_addr = new struct ifaddrs;
+    memset(if_addr, 0, sizeof(struct ifaddrs));
+    if_addr->ifa_name = if_name;
+    if_addr->ifa_addr =
+        reinterpret_cast<struct sockaddr*>(CreateIpv4Addr(ipv4_address));
+    if_addr->ifa_netmask =
+        reinterpret_cast<struct sockaddr*>(CreateIpv4Addr(ipv4_netmask));
+    if_addr->ifa_next = list;
+    if_addr->ifa_flags = IFF_RUNNING;
+    return if_addr;
+  }
+
+  struct ifaddrs* InstallIpv4Network(char* if_name,
+                                     const std::string& ipv4_address,
+                                     const std::string& ipv4_mask,
+                                     BasicNetworkManager& network_manager) {
+    ifaddrs* addr_list = nullptr;
+    addr_list = AddIpv4Address(addr_list, if_name, ipv4_address, ipv4_mask);
+    NetworkManager::NetworkList result;
+    bool changed;
+    NetworkManager::Stats stats;
+    CallConvertIfAddrs(network_manager, addr_list, true, &result);
+    network_manager.MergeNetworkList(result, &changed, &stats);
+    return addr_list;
+  }
+
   void ReleaseIfAddrs(struct ifaddrs* list) {
     struct ifaddrs* if_addr = list;
     while (if_addr != nullptr) {
@@ -802,6 +844,8 @@
 // a few cases. Note that UNKNOWN type for non-matching strings has been tested
 // in the above test.
 TEST_F(NetworkTest, TestGetAdapterTypeFromNameMatching) {
+  std::string ipv4_address1 = "192.0.0.121";
+  std::string ipv4_mask = "255.255.255.0";
   std::string ipv6_address1 = "1000:2000:3000:4000:0:0:0:1";
   std::string ipv6_address2 = "1000:2000:3000:8000:0:0:0:1";
   std::string ipv6_mask = "FFFF:FFFF:FFFF:FFFF::";
@@ -822,7 +866,7 @@
   ReleaseIfAddrs(addr_list);
 
   strcpy(if_name, "eth0");
-  addr_list = InstallIpv6Network(if_name, ipv6_address1, ipv6_mask, manager);
+  addr_list = InstallIpv4Network(if_name, ipv4_address1, ipv4_mask, manager);
   EXPECT_EQ(ADAPTER_TYPE_ETHERNET, GetAdapterType(manager));
   ClearNetworks(manager);
   ReleaseIfAddrs(addr_list);
@@ -858,6 +902,12 @@
   EXPECT_EQ(ADAPTER_TYPE_CELLULAR, GetAdapterType(manager));
   ClearNetworks(manager);
   ReleaseIfAddrs(addr_list);
+
+  strcpy(if_name, "clat4");
+  addr_list = InstallIpv4Network(if_name, ipv4_address1, ipv4_mask, manager);
+  EXPECT_EQ(ADAPTER_TYPE_CELLULAR, GetAdapterType(manager));
+  ClearNetworks(manager);
+  ReleaseIfAddrs(addr_list);
 #else
   // TODO(deadbeef): If not iOS or Android, "wlan0" should be treated as
   // "unknown"? Why? This should be fixed if there's no good reason.