Home | History | Annotate | Download | only in server
      1 /*
      2  * Copyright 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  *
     16  * sock_diag_test.cpp - unit tests for SockDiag.cpp
     17  */
     18 
     19 #include <sys/socket.h>
     20 #include <netdb.h>
     21 #include <arpa/inet.h>
     22 #include <netinet/in.h>
     23 #include <netinet/tcp.h>
     24 #include <linux/inet_diag.h>
     25 
     26 #include <gtest/gtest.h>
     27 
     28 #include "Fwmark.h"
     29 #include "NetdConstants.h"
     30 #include "SockDiag.h"
     31 #include "UidRanges.h"
     32 
     33 namespace android {
     34 namespace net {
     35 
     36 class SockDiagTest : public ::testing::Test {
     37 protected:
     38     static bool isLoopbackSocket(const inet_diag_msg *msg) {
     39         return SockDiag::isLoopbackSocket(msg);
     40     };
     41 };
     42 
     43 uint16_t bindAndListen(int s) {
     44     for (int i = 0; i < 10; i++) {
     45         uint16_t port = 1024 + arc4random_uniform(0xffff - 1024);
     46         sockaddr_in6 sin6 = { .sin6_family = AF_INET6, .sin6_port = htons(port) };
     47         if (bind(s, (sockaddr *) &sin6, sizeof(sin6)) == 0) {
     48             listen(s, 1);
     49             return port;
     50         }
     51     }
     52     close(s);
     53     return 0;
     54 }
     55 
     56 const char *tcpStateName(uint8_t state) {
     57     static const char *states[] = {
     58         "???",
     59         "TCP_ESTABLISHED",
     60         "TCP_SYN_SENT",
     61         "TCP_SYN_RECV",
     62         "TCP_FIN_WAIT1",
     63         "TCP_FIN_WAIT2",
     64         "TCP_TIME_WAIT",
     65         "TCP_CLOSE",
     66         "TCP_CLOSE_WAIT",
     67         "TCP_LAST_ACK",
     68         "TCP_LISTEN",
     69         "TCP_CLOSING",
     70         "TCP_NEW_SYN_RECV",
     71     };
     72     return states[(state < ARRAY_SIZE(states)) ? state : 0];
     73 }
     74 
     75 TEST_F(SockDiagTest, TestDump) {
     76     int v4socket = socket(AF_INET, SOCK_STREAM, 0);
     77     ASSERT_NE(-1, v4socket) << "Failed to open IPv4 socket: " << strerror(errno);
     78     int v6socket = socket(AF_INET6, SOCK_STREAM, 0);
     79     ASSERT_NE(-1, v6socket) << "Failed to open IPv6 socket: " << strerror(errno);
     80     int listensocket = socket(AF_INET6, SOCK_STREAM, 0);
     81     ASSERT_NE(-1, listensocket) << "Failed to open listen socket: " << strerror(errno);
     82 
     83     uint16_t port = bindAndListen(listensocket);
     84     ASSERT_NE(0, port) << "Can't bind to server port";
     85 
     86     // Connect to loopback.
     87     sockaddr_in server4 = { .sin_family = AF_INET, .sin_port = htons(port) };
     88     sockaddr_in6 server6 = { .sin6_family = AF_INET6, .sin6_port = htons(port) };
     89     ASSERT_EQ(0, connect(v4socket, (sockaddr *) &server4, sizeof(server4)))
     90         << "IPv4 connect failed: " << strerror(errno);
     91     ASSERT_EQ(0, connect(v6socket, (sockaddr *) &server6, sizeof(server6)))
     92         << "IPv6 connect failed: " << strerror(errno);
     93 
     94     sockaddr_in6 client46, client6;
     95     socklen_t clientlen = std::max(sizeof(client46), sizeof(client6));
     96     int accepted4 = accept(listensocket, (sockaddr *) &client46, &clientlen);
     97     int accepted6 = accept(listensocket, (sockaddr *) &client6, &clientlen);
     98     ASSERT_NE(-1, accepted4);
     99     ASSERT_NE(-1, accepted6);
    100 
    101     int v4SocketsSeen = 0;
    102     bool seenclient46 = false;
    103     char src[INET6_ADDRSTRLEN], dst[INET6_ADDRSTRLEN];
    104 
    105     fprintf(stderr, "Ports:\n  server=%d. client46=%d, client6=%d\n",
    106             port, ntohs(client46.sin6_port), ntohs(client6.sin6_port));
    107 
    108     auto checkIPv4Dump = [&] (uint8_t /* proto */, const inet_diag_msg *msg) {
    109         EXPECT_EQ(htonl(INADDR_LOOPBACK), msg->id.idiag_src[0]);
    110         v4SocketsSeen++;
    111         seenclient46 |= (msg->id.idiag_sport == client46.sin6_port);
    112         inet_ntop(AF_INET, msg->id.idiag_src, src, sizeof(src));
    113         inet_ntop(AF_INET, msg->id.idiag_src, dst, sizeof(dst));
    114         fprintf(stderr, "  v4 %s:%d -> %s:%d %s\n",
    115                 src, htons(msg->id.idiag_sport),
    116                 dst, htons(msg->id.idiag_dport),
    117                 tcpStateName(msg->idiag_state));
    118         if (msg->idiag_state == TCP_ESTABLISHED) {
    119             EXPECT_TRUE(isLoopbackSocket(msg));
    120         }
    121         return false;
    122     };
    123 
    124     int v6SocketsSeen = 0;
    125     bool seenClient6 = false, seenServer46 = false, seenServer6 = false;
    126 
    127     auto checkIPv6Dump = [&] (uint8_t /* proto */, const inet_diag_msg *msg) {
    128         struct in6_addr *saddr = (struct in6_addr *) msg->id.idiag_src;
    129         EXPECT_TRUE(
    130             IN6_IS_ADDR_LOOPBACK(saddr) ||
    131             (IN6_IS_ADDR_V4MAPPED(saddr) && saddr->s6_addr32[3] == htonl(INADDR_LOOPBACK)));
    132         v6SocketsSeen++;
    133         seenClient6 |= (msg->id.idiag_sport == client6.sin6_port);
    134         seenServer46 |= (msg->id.idiag_sport == htons(port));
    135         seenServer6 |= (msg->id.idiag_sport == htons(port));
    136         inet_ntop(AF_INET6, msg->id.idiag_src, src, sizeof(src));
    137         inet_ntop(AF_INET6, msg->id.idiag_src, dst, sizeof(dst));
    138         fprintf(stderr, "  v6 [%s]:%d -> [%s]:%d %s\n",
    139                 src, htons(msg->id.idiag_sport),
    140                 dst, htons(msg->id.idiag_dport),
    141                 tcpStateName(msg->idiag_state));
    142         if (msg->idiag_state == TCP_ESTABLISHED) {
    143             EXPECT_TRUE(isLoopbackSocket(msg));
    144         }
    145         return false;
    146     };
    147 
    148     SockDiag sd;
    149     ASSERT_TRUE(sd.open()) << "Failed to open SOCK_DIAG socket";
    150 
    151     int ret = sd.sendDumpRequest(IPPROTO_TCP, AF_INET, "127.0.0.1");
    152     ASSERT_EQ(0, ret) << "Failed to send IPv4 dump request: " << strerror(-ret);
    153     fprintf(stderr, "Sent IPv4 dump\n");
    154     sd.readDiagMsg(IPPROTO_TCP, checkIPv4Dump);
    155     EXPECT_GE(v4SocketsSeen, 1);
    156     EXPECT_TRUE(seenclient46);
    157     EXPECT_FALSE(seenServer46);
    158 
    159     ret = sd.sendDumpRequest(IPPROTO_TCP, AF_INET6, "127.0.0.1");
    160     ASSERT_EQ(0, ret) << "Failed to send mapped dump request: " << strerror(-ret);
    161     fprintf(stderr, "Sent mapped dump\n");
    162     sd.readDiagMsg(IPPROTO_TCP, checkIPv6Dump);
    163     EXPECT_TRUE(seenServer46);
    164 
    165     ret = sd.sendDumpRequest(IPPROTO_TCP, AF_INET6, "::1");
    166     ASSERT_EQ(0, ret) << "Failed to send IPv6 dump request: " << strerror(-ret);
    167     fprintf(stderr, "Sent IPv6 dump\n");
    168 
    169     sd.readDiagMsg(IPPROTO_TCP, checkIPv6Dump);
    170     EXPECT_GE(v6SocketsSeen, 1);
    171     EXPECT_TRUE(seenClient6);
    172     EXPECT_TRUE(seenServer6);
    173 
    174     close(v4socket);
    175     close(v6socket);
    176     close(listensocket);
    177     close(accepted4);
    178     close(accepted6);
    179 }
    180 
    181 bool fillDiagAddr(__be32 addr[4], const sockaddr *sa) {
    182     switch (sa->sa_family) {
    183         case AF_INET: {
    184             sockaddr_in *sin = (sockaddr_in *) sa;
    185             memcpy(addr, &sin->sin_addr, sizeof(sin->sin_addr));
    186             return true;
    187         }
    188         case AF_INET6: {
    189             sockaddr_in6 *sin6 = (sockaddr_in6 *) sa;
    190             memcpy(addr, &sin6->sin6_addr, sizeof(sin6->sin6_addr));
    191             return true;
    192         }
    193         default:
    194             return false;
    195     }
    196 }
    197 
    198 inet_diag_msg makeDiagMessage(__u8 family,  const sockaddr *src, const sockaddr *dst) {
    199     inet_diag_msg msg = {
    200         .idiag_family = family,
    201         .idiag_state = TCP_ESTABLISHED,
    202         .idiag_uid = AID_APP + 123,
    203         .idiag_inode = 123456789,
    204         .id = {
    205             .idiag_sport = 1234,
    206             .idiag_dport = 4321,
    207         }
    208     };
    209     EXPECT_TRUE(fillDiagAddr(msg.id.idiag_src, src));
    210     EXPECT_TRUE(fillDiagAddr(msg.id.idiag_dst, dst));
    211     return msg;
    212 }
    213 
    214 inet_diag_msg makeDiagMessage(const char* srcstr, const char* dststr) {
    215     addrinfo hints = { .ai_flags = AI_NUMERICHOST }, *src, *dst;
    216     EXPECT_EQ(0, getaddrinfo(srcstr, NULL, &hints, &src));
    217     EXPECT_EQ(0, getaddrinfo(dststr, NULL, &hints, &dst));
    218     EXPECT_EQ(src->ai_addr->sa_family, dst->ai_addr->sa_family);
    219     inet_diag_msg msg = makeDiagMessage(src->ai_addr->sa_family, src->ai_addr, dst->ai_addr);
    220     freeaddrinfo(src);
    221     freeaddrinfo(dst);
    222     return msg;
    223 }
    224 
    225 TEST_F(SockDiagTest, TestIsLoopbackSocket) {
    226     inet_diag_msg msg;
    227 
    228     msg = makeDiagMessage("127.0.0.1", "127.0.0.1");
    229     EXPECT_TRUE(isLoopbackSocket(&msg));
    230 
    231     msg = makeDiagMessage("::1", "::1");
    232     EXPECT_TRUE(isLoopbackSocket(&msg));
    233 
    234     msg = makeDiagMessage("::1", "::ffff:127.0.0.1");
    235     EXPECT_TRUE(isLoopbackSocket(&msg));
    236 
    237     msg = makeDiagMessage("192.0.2.1", "192.0.2.1");
    238     EXPECT_TRUE(isLoopbackSocket(&msg));
    239 
    240     msg = makeDiagMessage("192.0.2.1", "8.8.8.8");
    241     EXPECT_FALSE(isLoopbackSocket(&msg));
    242 
    243     msg = makeDiagMessage("192.0.2.1", "127.0.0.1");
    244     EXPECT_TRUE(isLoopbackSocket(&msg));
    245 
    246     msg = makeDiagMessage("2001:db8::1", "2001:db8::1");
    247     EXPECT_TRUE(isLoopbackSocket(&msg));
    248 
    249     msg = makeDiagMessage("2001:db8::1", "2001:4860:4860::6464");
    250     EXPECT_FALSE(isLoopbackSocket(&msg));
    251 
    252     // While isLoopbackSocket returns true on these sockets, we usually don't want to close them
    253     // because they aren't specific to any particular network and thus don't become unusable when
    254     // an app's routing changes or its network access is removed.
    255     //
    256     // This isn't a problem, as anything that calls destroyLiveSockets will skip them because
    257     // destroyLiveSockets only enumerates ESTABLISHED, SYN_SENT, and SYN_RECV sockets.
    258     msg = makeDiagMessage("127.0.0.1", "0.0.0.0");
    259     EXPECT_TRUE(isLoopbackSocket(&msg));
    260 
    261     msg = makeDiagMessage("::1", "::");
    262     EXPECT_TRUE(isLoopbackSocket(&msg));
    263 }
    264 
    265 enum MicroBenchmarkTestType {
    266     ADDRESS,
    267     UID,
    268     UID_EXCLUDE_LOOPBACK,
    269     UIDRANGE,
    270     UIDRANGE_EXCLUDE_LOOPBACK,
    271     PERMISSION,
    272 };
    273 
    274 const char *testTypeName(MicroBenchmarkTestType mode) {
    275 #define TO_STRING_TYPE(x) case ((x)): return #x;
    276     switch((mode)) {
    277         TO_STRING_TYPE(ADDRESS);
    278         TO_STRING_TYPE(UID);
    279         TO_STRING_TYPE(UID_EXCLUDE_LOOPBACK);
    280         TO_STRING_TYPE(UIDRANGE);
    281         TO_STRING_TYPE(UIDRANGE_EXCLUDE_LOOPBACK);
    282         TO_STRING_TYPE(PERMISSION);
    283     }
    284 #undef TO_STRING_TYPE
    285 }
    286 
    287 static struct {
    288     unsigned netId;
    289     bool explicitlySelected;
    290     Permission permission;
    291 } permissionTestcases[] = {
    292     { 42, false, PERMISSION_NONE,    },
    293     { 42, false, PERMISSION_NETWORK, },
    294     { 42, false, PERMISSION_SYSTEM,  },
    295     { 42, true,  PERMISSION_NONE,    },
    296     { 42, true,  PERMISSION_NETWORK, },
    297     { 42, true,  PERMISSION_SYSTEM,  },
    298     { 43, false, PERMISSION_NONE,    },
    299     { 43, false, PERMISSION_NETWORK, },
    300     { 43, false, PERMISSION_SYSTEM,  },
    301     { 43, true,  PERMISSION_NONE,    },
    302     { 43, true,  PERMISSION_NETWORK, },
    303     { 43, true,  PERMISSION_SYSTEM,  },
    304 };
    305 
    306 class SockDiagMicroBenchmarkTest : public ::testing::TestWithParam<MicroBenchmarkTestType> {
    307 
    308 public:
    309     void SetUp() {
    310         ASSERT_TRUE(mSd.open()) << "Failed to open SOCK_DIAG socket";
    311     }
    312 
    313 protected:
    314     SockDiag mSd;
    315 
    316     constexpr static int MAX_SOCKETS = 500;
    317     constexpr static int ADDRESS_SOCKETS = 500;
    318     constexpr static int UID_SOCKETS = 50;
    319     constexpr static int PERMISSION_SOCKETS = 16;
    320 
    321     constexpr static uid_t START_UID = 8000;  // START_UID + number of sockets must be <= 9999.
    322     constexpr static int CLOSE_UID = START_UID + UID_SOCKETS - 42;  // Close to the end
    323     static_assert(START_UID + MAX_SOCKETS < 9999, "Too many sockets");
    324 
    325     constexpr static int TEST_NETID = 42;  // One of the OEM netIds.
    326 
    327 
    328     int howManySockets() {
    329         MicroBenchmarkTestType mode = GetParam();
    330         switch (mode) {
    331         case ADDRESS:
    332             return ADDRESS_SOCKETS;
    333         case UID:
    334         case UID_EXCLUDE_LOOPBACK:
    335         case UIDRANGE:
    336         case UIDRANGE_EXCLUDE_LOOPBACK:
    337             return UID_SOCKETS;
    338         case PERMISSION:
    339             return ARRAY_SIZE(permissionTestcases);
    340         }
    341     }
    342 
    343     int modifySocketForTest(int s, int i) {
    344         MicroBenchmarkTestType mode = GetParam();
    345         switch (mode) {
    346         case UID:
    347         case UID_EXCLUDE_LOOPBACK:
    348         case UIDRANGE:
    349         case UIDRANGE_EXCLUDE_LOOPBACK: {
    350             uid_t uid = START_UID + i;
    351             return fchown(s, uid, -1);
    352         }
    353         case PERMISSION: {
    354             Fwmark fwmark;
    355             fwmark.netId = permissionTestcases[i].netId;
    356             fwmark.explicitlySelected = permissionTestcases[i].explicitlySelected;
    357             fwmark.permission = permissionTestcases[i].permission;
    358             return setsockopt(s, SOL_SOCKET, SO_MARK, &fwmark.intValue, sizeof(fwmark.intValue));
    359         }
    360         default:
    361             return 0;
    362         }
    363     }
    364 
    365     int destroySockets() {
    366         MicroBenchmarkTestType mode = GetParam();
    367         int ret;
    368         switch (mode) {
    369             case ADDRESS:
    370                 ret = mSd.destroySockets("::1");
    371                 EXPECT_LE(0, ret) << ": Failed to destroy sockets on ::1: " << strerror(-ret);
    372                 break;
    373             case UID:
    374             case UID_EXCLUDE_LOOPBACK: {
    375                 bool excludeLoopback = (mode == UID_EXCLUDE_LOOPBACK);
    376                 ret = mSd.destroySockets(IPPROTO_TCP, CLOSE_UID, excludeLoopback);
    377                 EXPECT_LE(0, ret) << ": Failed to destroy sockets for UID " << CLOSE_UID << ": " <<
    378                         strerror(-ret);
    379                 break;
    380             }
    381             case UIDRANGE:
    382             case UIDRANGE_EXCLUDE_LOOPBACK: {
    383                 bool excludeLoopback = (mode == UIDRANGE_EXCLUDE_LOOPBACK);
    384                 const char *uidRangeStrings[] = { "8005-8012", "8042", "8043", "8090-8099" };
    385                 std::set<uid_t> skipUids { 8007, 8043, 8098, 8099 };
    386                 UidRanges uidRanges;
    387                 uidRanges.parseFrom(ARRAY_SIZE(uidRangeStrings), (char **) uidRangeStrings);
    388                 ret = mSd.destroySockets(uidRanges, skipUids, excludeLoopback);
    389                 break;
    390             }
    391             case PERMISSION: {
    392                 ret = mSd.destroySocketsLackingPermission(TEST_NETID, PERMISSION_NETWORK, false);
    393                 break;
    394             }
    395         }
    396         return ret;
    397     }
    398 
    399     bool shouldHaveClosedSocket(int i) {
    400         MicroBenchmarkTestType mode = GetParam();
    401         switch (mode) {
    402             case ADDRESS:
    403                 return true;
    404             case UID:
    405                 return i == CLOSE_UID - START_UID;
    406             case UIDRANGE: {
    407                 uid_t uid = i + START_UID;
    408                 // Skip UIDs in skipUids.
    409                 if (uid == 8007 || uid == 8043 || uid == 8098 || uid == 8099) {
    410                     return false;
    411                 }
    412                 // Include UIDs in uidRanges.
    413                 if ((8005 <= uid && uid <= 8012) || uid == 8042 || (8090 <= uid && uid <= 8099)) {
    414                     return true;
    415                 }
    416                 return false;
    417             }
    418             case UID_EXCLUDE_LOOPBACK:
    419             case UIDRANGE_EXCLUDE_LOOPBACK:
    420                 return false;
    421             case PERMISSION:
    422                 if (permissionTestcases[i].netId != 42) return false;
    423                 if (permissionTestcases[i].explicitlySelected != 1) return true;
    424                 Permission permission = permissionTestcases[i].permission;
    425                 return permission != PERMISSION_NETWORK && permission != PERMISSION_SYSTEM;
    426         }
    427     }
    428 
    429     bool checkSocketState(int i, int sock, const char *msg) {
    430         const char data[] = "foo";
    431         const int ret = send(sock, data, sizeof(data), 0);
    432         const int err = errno;
    433         if (!shouldHaveClosedSocket(i)) {
    434             EXPECT_EQ((ssize_t) sizeof(data), ret) <<
    435                     "Write on open socket failed: " << strerror(err);
    436             return false;
    437         }
    438 
    439         EXPECT_EQ(-1, ret) << msg << " " << i << " not closed";
    440         if (ret != -1) {
    441             return false;
    442         }
    443 
    444         // Since we're connected to ourselves, the error might be ECONNABORTED (if we destroyed the
    445         // socket) or ECONNRESET (if the other end was destroyed and sent a RST).
    446         EXPECT_TRUE(err == ECONNABORTED || err == ECONNRESET)
    447             << msg << ": unexpected error: " << strerror(err);
    448         return (err == ECONNABORTED);  // Return true iff. SOCK_DESTROY closed this socket.
    449     }
    450 };
    451 
    452 TEST_P(SockDiagMicroBenchmarkTest, TestMicroBenchmark) {
    453     MicroBenchmarkTestType mode = GetParam();
    454 
    455     int numSockets = howManySockets();
    456 
    457     fprintf(stderr, "Benchmarking closing %d sockets based on %s\n",
    458             numSockets, testTypeName(mode));
    459 
    460     int listensocket = socket(AF_INET6, SOCK_STREAM, 0);
    461     ASSERT_NE(-1, listensocket) << "Failed to open listen socket";
    462 
    463     uint16_t port = bindAndListen(listensocket);
    464     ASSERT_NE(0, port) << "Can't bind to server port";
    465     sockaddr_in6 server = { .sin6_family = AF_INET6, .sin6_port = htons(port) };
    466 
    467     using ms = std::chrono::duration<float, std::ratio<1, 1000>>;
    468 
    469     int clientsockets[MAX_SOCKETS], serversockets[MAX_SOCKETS];
    470     uint16_t clientports[MAX_SOCKETS];
    471     sockaddr_in6 client;
    472     socklen_t clientlen;
    473 
    474     auto start = std::chrono::steady_clock::now();
    475     for (int i = 0; i < numSockets; i++) {
    476         int s = socket(AF_INET6, SOCK_STREAM, 0);
    477         clientlen = sizeof(client);
    478         ASSERT_EQ(0, connect(s, (sockaddr *) &server, sizeof(server)))
    479             << "Connecting socket " << i << " failed " << strerror(errno);
    480         ASSERT_EQ(0, modifySocketForTest(s, i));
    481         serversockets[i] = accept(listensocket, (sockaddr *) &client, &clientlen);
    482         ASSERT_NE(-1, serversockets[i])
    483             << "Accepting socket " << i << " failed " << strerror(errno);
    484         clientports[i] = client.sin6_port;
    485         clientsockets[i] = s;
    486     }
    487     fprintf(stderr, "  Connecting: %6.1f ms\n",
    488             std::chrono::duration_cast<ms>(std::chrono::steady_clock::now() - start).count());
    489 
    490     start = std::chrono::steady_clock::now();
    491     destroySockets();
    492     fprintf(stderr, "  Destroying: %6.1f ms\n",
    493             std::chrono::duration_cast<ms>(std::chrono::steady_clock::now() - start).count());
    494 
    495     start = std::chrono::steady_clock::now();
    496     int socketsClosed = 0;
    497     for (int i = 0; i < numSockets; i++) {
    498         socketsClosed += checkSocketState(i, clientsockets[i], "Client socket");
    499         socketsClosed += checkSocketState(i, serversockets[i], "Server socket");
    500     }
    501     fprintf(stderr, "   Verifying: %6.1f ms (%d sockets destroyed)\n",
    502             std::chrono::duration_cast<ms>(std::chrono::steady_clock::now() - start).count(),
    503             socketsClosed);
    504     if (strstr(testTypeName(mode), "_EXCLUDE_LOOPBACK") == nullptr) {
    505         EXPECT_GT(socketsClosed, 0);  // Just in case there's a bug in the test.
    506     }
    507 
    508     start = std::chrono::steady_clock::now();
    509     for (int i = 0; i < numSockets; i++) {
    510         close(clientsockets[i]);
    511         close(serversockets[i]);
    512     }
    513     fprintf(stderr, "     Closing: %6.1f ms\n",
    514             std::chrono::duration_cast<ms>(std::chrono::steady_clock::now() - start).count());
    515 
    516     close(listensocket);
    517 }
    518 
    519 // "SockDiagTest.cpp:232: error: undefined reference to 'SockDiagMicroBenchmarkTest::CLOSE_UID'".
    520 constexpr int SockDiagMicroBenchmarkTest::CLOSE_UID;
    521 
    522 INSTANTIATE_TEST_CASE_P(Address, SockDiagMicroBenchmarkTest,
    523                         testing::Values(ADDRESS, UID, UIDRANGE,
    524                                         UID_EXCLUDE_LOOPBACK, UIDRANGE_EXCLUDE_LOOPBACK,
    525                                         PERMISSION));
    526 
    527 }  // namespace net
    528 }  // namespace android
    529