1 /* 2 * Copyright (C) 2018 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 17 package com.android.net.module.util.netlink; 18 19 import static android.os.Process.ROOT_UID; 20 import static android.os.Process.SHELL_UID; 21 import static android.system.OsConstants.AF_INET; 22 import static android.system.OsConstants.AF_INET6; 23 import static android.system.OsConstants.IPPROTO_TCP; 24 import static android.system.OsConstants.IPPROTO_UDP; 25 import static android.system.OsConstants.NETLINK_INET_DIAG; 26 27 import static com.android.net.module.util.netlink.NetlinkConstants.SOCK_DESTROY; 28 import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_ACK; 29 import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_DUMP; 30 import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REQUEST; 31 32 import static org.junit.Assert.assertArrayEquals; 33 import static org.junit.Assert.assertEquals; 34 import static org.junit.Assert.assertNotNull; 35 import static org.junit.Assert.assertNull; 36 import static org.junit.Assert.assertTrue; 37 import static org.junit.Assert.fail; 38 39 import android.net.InetAddresses; 40 import android.util.ArraySet; 41 import android.util.Range; 42 43 import androidx.test.filters.SmallTest; 44 import androidx.test.runner.AndroidJUnit4; 45 46 import libcore.util.HexEncoding; 47 48 import org.junit.Test; 49 import org.junit.runner.RunWith; 50 51 import java.net.Inet6Address; 52 import java.net.InetAddress; 53 import java.net.InetSocketAddress; 54 import java.net.UnknownHostException; 55 import java.nio.ByteBuffer; 56 import java.nio.ByteOrder; 57 import java.util.List; 58 import java.util.Set; 59 60 @RunWith(AndroidJUnit4.class) 61 @SmallTest 62 public class InetDiagSocketTest { 63 // ::FFFF:192.0.2.1 64 private static final byte[] SRC_V4_MAPPED_V6_ADDRESS_BYTES = { 65 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 66 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 67 (byte) 0x00, (byte) 0x00, (byte) 0xff, (byte) 0xff, 68 (byte) 0xc0, (byte) 0x00, (byte) 0x02, (byte) 0x01, 69 }; 70 // ::FFFF:192.0.2.2 71 private static final byte[] DST_V4_MAPPED_V6_ADDRESS_BYTES = { 72 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 73 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 74 (byte) 0x00, (byte) 0x00, (byte) 0xff, (byte) 0xff, 75 (byte) 0xc0, (byte) 0x00, (byte) 0x02, (byte) 0x02, 76 }; 77 78 // Hexadecimal representation of InetDiagReqV2 request. 79 private static final String INET_DIAG_REQ_V2_UDP_INET4_HEX = 80 // struct nlmsghdr 81 "48000000" + // length = 72 82 "1400" + // type = SOCK_DIAG_BY_FAMILY 83 "0103" + // flags = NLM_F_REQUEST | NLM_F_DUMP 84 "00000000" + // seqno 85 "00000000" + // pid (0 == kernel) 86 // struct inet_diag_req_v2 87 "02" + // family = AF_INET 88 "11" + // protcol = IPPROTO_UDP 89 "00" + // idiag_ext 90 "00" + // pad 91 "ffffffff" + // idiag_states 92 // inet_diag_sockid 93 "a5de" + // idiag_sport = 42462 94 "b971" + // idiag_dport = 47473 95 "0a006402000000000000000000000000" + // idiag_src = 10.0.100.2 96 "08080808000000000000000000000000" + // idiag_dst = 8.8.8.8 97 "00000000" + // idiag_if 98 "ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE 99 private static final byte[] INET_DIAG_REQ_V2_UDP_INET4_BYTES = 100 HexEncoding.decode(INET_DIAG_REQ_V2_UDP_INET4_HEX.toCharArray(), false); 101 102 @Test testInetDiagReqV2UdpInet4()103 public void testInetDiagReqV2UdpInet4() throws Exception { 104 InetSocketAddress local = new InetSocketAddress(InetAddress.getByName("10.0.100.2"), 105 42462); 106 InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"), 107 47473); 108 final byte[] msg = InetDiagMessage.inetDiagReqV2(IPPROTO_UDP, local, remote, AF_INET, 109 (short) (NLM_F_REQUEST | NLM_F_DUMP)); 110 assertArrayEquals(INET_DIAG_REQ_V2_UDP_INET4_BYTES, msg); 111 } 112 113 // Hexadecimal representation of InetDiagReqV2 request. 114 private static final String INET_DIAG_REQ_V2_TCP_INET6_HEX = 115 // struct nlmsghdr 116 "48000000" + // length = 72 117 "1400" + // type = SOCK_DIAG_BY_FAMILY 118 "0100" + // flags = NLM_F_REQUEST 119 "00000000" + // seqno 120 "00000000" + // pid (0 == kernel) 121 // struct inet_diag_req_v2 122 "0a" + // family = AF_INET6 123 "06" + // protcol = IPPROTO_TCP 124 "00" + // idiag_ext 125 "00" + // pad 126 "ffffffff" + // idiag_states 127 // inet_diag_sockid 128 "a5de" + // idiag_sport = 42462 129 "b971" + // idiag_dport = 47473 130 "fe8000000000000086c9b2fffe6aed4b" + // idiag_src = fe80::86c9:b2ff:fe6a:ed4b 131 "08080808000000000000000000000000" + // idiag_dst = 8.8.8.8 132 "00000000" + // idiag_if 133 "ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE 134 private static final byte[] INET_DIAG_REQ_V2_TCP_INET6_BYTES = 135 HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET6_HEX.toCharArray(), false); 136 137 @Test testInetDiagReqV2TcpInet6()138 public void testInetDiagReqV2TcpInet6() throws Exception { 139 InetSocketAddress local = new InetSocketAddress( 140 InetAddress.getByName("fe80::86c9:b2ff:fe6a:ed4b"), 42462); 141 InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"), 142 47473); 143 byte[] msg = InetDiagMessage.inetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET6, 144 NLM_F_REQUEST); 145 146 assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_BYTES, msg); 147 } 148 149 // Hexadecimal representation of InetDiagReqV2 request with extension, INET_DIAG_INFO. 150 private static final String INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_HEX = 151 // struct nlmsghdr 152 "48000000" + // length = 72 153 "1400" + // type = SOCK_DIAG_BY_FAMILY 154 "0100" + // flags = NLM_F_REQUEST 155 "00000000" + // seqno 156 "00000000" + // pid (0 == kernel) 157 // struct inet_diag_req_v2 158 "02" + // family = AF_INET 159 "06" + // protcol = IPPROTO_TCP 160 "02" + // idiag_ext = INET_DIAG_INFO 161 "00" + // pad 162 "ffffffff" + // idiag_states 163 // inet_diag_sockid 164 "3039" + // idiag_sport = 12345 165 "d431" + // idiag_dport = 54321 166 "01020304000000000000000000000000" + // idiag_src = 1.2.3.4 167 "08080404000000000000000000000000" + // idiag_dst = 8.8.4.4 168 "00000000" + // idiag_if 169 "ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE 170 171 private static final byte[] INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_BYTES = 172 HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_HEX.toCharArray(), false); 173 private static final int TCP_ALL_STATES = 0xffffffff; 174 @Test testInetDiagReqV2TcpInetWithExt()175 public void testInetDiagReqV2TcpInetWithExt() throws Exception { 176 InetSocketAddress local = new InetSocketAddress( 177 InetAddress.getByName("1.2.3.4"), 12345); 178 InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.4.4"), 179 54321); 180 byte[] msg = InetDiagMessage.inetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET, 181 NLM_F_REQUEST, 0 /* pad */, 2 /* idiagExt */, TCP_ALL_STATES); 182 183 assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_BYTES, msg); 184 185 local = new InetSocketAddress( 186 InetAddress.getByName("fe80::86c9:b2ff:fe6a:ed4b"), 42462); 187 remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"), 188 47473); 189 msg = InetDiagMessage.inetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET6, 190 NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES); 191 192 assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_BYTES, msg); 193 } 194 195 // Hexadecimal representation of InetDiagReqV2 request with no socket specified. 196 private static final String INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFIED_HEX = 197 // struct nlmsghdr 198 "48000000" + // length = 72 199 "1400" + // type = SOCK_DIAG_BY_FAMILY 200 "0100" + // flags = NLM_F_REQUEST 201 "00000000" + // seqno 202 "00000000" + // pid (0 == kernel) 203 // struct inet_diag_req_v2 204 "0a" + // family = AF_INET6 205 "06" + // protcol = IPPROTO_TCP 206 "00" + // idiag_ext 207 "00" + // pad 208 "ffffffff" + // idiag_states 209 // inet_diag_sockid 210 "0000" + // idiag_sport 211 "0000" + // idiag_dport 212 "00000000000000000000000000000000" + // idiag_src 213 "00000000000000000000000000000000" + // idiag_dst 214 "00000000" + // idiag_if 215 "0000000000000000"; // idiag_cookie 216 217 private static final byte[] INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFIED_BYTES = 218 HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFIED_HEX.toCharArray(), false); 219 220 @Test testInetDiagReqV2TcpInet6NoIdSpecified()221 public void testInetDiagReqV2TcpInet6NoIdSpecified() throws Exception { 222 InetSocketAddress local = new InetSocketAddress( 223 InetAddress.getByName("fe80::fe6a:ed4b"), 12345); 224 InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.4.4"), 225 54321); 226 // Verify no socket specified if either local or remote socket address is null. 227 byte[] msgExt = InetDiagMessage.inetDiagReqV2(IPPROTO_TCP, null, null, AF_INET6, 228 NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES); 229 byte[] msg; 230 try { 231 msg = InetDiagMessage.inetDiagReqV2(IPPROTO_TCP, null, remote, AF_INET6, 232 NLM_F_REQUEST); 233 fail("Both remote and local should be null, expected UnknownHostException"); 234 } catch (IllegalArgumentException e) { 235 } 236 237 try { 238 msg = InetDiagMessage.inetDiagReqV2(IPPROTO_TCP, local, null, AF_INET6, 239 NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES); 240 fail("Both remote and local should be null, expected UnknownHostException"); 241 } catch (IllegalArgumentException e) { 242 } 243 244 msg = InetDiagMessage.inetDiagReqV2(IPPROTO_TCP, null, null, AF_INET6, 245 NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES); 246 assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFIED_BYTES, msg); 247 assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFIED_BYTES, msgExt); 248 } 249 250 // Hexadecimal representation of InetDiagReqV2 request with v4-mapped v6 address 251 private static final String INET_DIAG_REQ_V2_TCP_INET6_V4_MAPPED_HEX = 252 // struct nlmsghdr 253 "48000000" + // length = 72 254 "1400" + // type = SOCK_DIAG_BY_FAMILY 255 "0100" + // flags = NLM_F_REQUEST 256 "00000000" + // seqno 257 "00000000" + // pid (0 == kernel) 258 // struct inet_diag_req_v2 259 "0a" + // family = AF_INET6 260 "06" + // protcol = IPPROTO_TCP 261 "00" + // idiag_ext 262 "00" + // pad 263 "ffffffff" + // idiag_states 264 // inet_diag_sockid 265 "a817" + // idiag_sport = 43031 266 "960f" + // idiag_dport = 38415 267 "00000000000000000000ffffc0000201" + // idiag_src = ::FFFF:192.0.2.1 268 "00000000000000000000ffffc0000202" + // idiag_dst = ::FFFF:192.0.2.2 269 "00000000" + // idiag_if 270 "ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE 271 272 private static final byte[] INET_DIAG_REQ_V2_TCP_INET6_V4_MAPPED_BYTES = 273 HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET6_V4_MAPPED_HEX.toCharArray(), false); 274 275 @Test testInetDiagReqV2TcpInet6V4Mapped()276 public void testInetDiagReqV2TcpInet6V4Mapped() throws Exception { 277 final Inet6Address srcAddr = Inet6Address.getByAddress( 278 null /* host */, SRC_V4_MAPPED_V6_ADDRESS_BYTES, -1 /* scope_id */); 279 final Inet6Address dstAddr = Inet6Address.getByAddress( 280 null /* host */, DST_V4_MAPPED_V6_ADDRESS_BYTES, -1 /* scope_id */); 281 final byte[] msg = InetDiagMessage.inetDiagReqV2( 282 IPPROTO_TCP, 283 new InetSocketAddress(srcAddr, 43031), 284 new InetSocketAddress(dstAddr, 38415), 285 AF_INET6, 286 NLM_F_REQUEST); 287 assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_V4_MAPPED_BYTES, msg); 288 } 289 290 // Hexadecimal representation of InetDiagReqV2 request with SOCK_DESTROY 291 private static final String INET_DIAG_REQ_V2_TCP_INET6_DESTROY_HEX = 292 // struct nlmsghdr 293 "48000000" + // length = 72 294 "1500" + // type = SOCK_DESTROY 295 "0500" + // flags = NLM_F_REQUEST | NLM_F_ACK 296 "00000000" + // seqno 297 "00000000" + // pid (0 == kernel) 298 // struct inet_diag_req_v2 299 "0a" + // family = AF_INET6 300 "06" + // protcol = IPPROTO_TCP 301 "00" + // idiag_ext 302 "00" + // pad 303 "ffffffff" + // idiag_states = TCP_ALL_STATES 304 // inet_diag_sockid 305 "a817" + // idiag_sport = 43031 306 "960f" + // idiag_dport = 38415 307 "20010db8000000000000000000000001" + // idiag_src = 2001:db8::1 308 "20010db8000000000000000000000002" + // idiag_dst = 2001:db8::2 309 "07000000" + // idiag_if = 7 310 "5800000000000000"; // idiag_cookie = 88 311 312 private static final byte[] INET_DIAG_REQ_V2_TCP_INET6_DESTROY_BYTES = 313 HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET6_DESTROY_HEX.toCharArray(), false); 314 315 @Test testInetDiagReqV2TcpInet6Destroy()316 public void testInetDiagReqV2TcpInet6Destroy() throws Exception { 317 final StructInetDiagSockId sockId = new StructInetDiagSockId( 318 new InetSocketAddress(InetAddresses.parseNumericAddress("2001:db8::1"), 43031), 319 new InetSocketAddress(InetAddresses.parseNumericAddress("2001:db8::2"), 38415), 320 7 /* ifIndex */, 321 88 /* cookie */); 322 final byte[] msg = InetDiagMessage.inetDiagReqV2(IPPROTO_TCP, sockId, AF_INET6, 323 SOCK_DESTROY, (short) (NLM_F_REQUEST | NLM_F_ACK), 0 /* pad */, 0 /* idiagExt */, 324 TCP_ALL_STATES); 325 326 assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_DESTROY_BYTES, msg); 327 } 328 assertNlMsgHdr(StructNlMsgHdr hdr, short type, short flags, int seq, int pid)329 private void assertNlMsgHdr(StructNlMsgHdr hdr, short type, short flags, int seq, int pid) { 330 assertNotNull(hdr); 331 assertEquals(type, hdr.nlmsg_type); 332 assertEquals(flags, hdr.nlmsg_flags); 333 assertEquals(seq, hdr.nlmsg_seq); 334 assertEquals(pid, hdr.nlmsg_pid); 335 } 336 assertInetDiagSockId(StructInetDiagSockId sockId, InetSocketAddress locSocketAddress, InetSocketAddress remSocketAddress, int ifIndex, long cookie)337 private void assertInetDiagSockId(StructInetDiagSockId sockId, 338 InetSocketAddress locSocketAddress, InetSocketAddress remSocketAddress, 339 int ifIndex, long cookie) { 340 assertEquals(locSocketAddress, sockId.locSocketAddress); 341 assertEquals(remSocketAddress, sockId.remSocketAddress); 342 assertEquals(ifIndex, sockId.ifIndex); 343 assertEquals(cookie, sockId.cookie); 344 } 345 346 // Hexadecimal representation of InetDiagMessage 347 private static final String INET_DIAG_MSG_HEX1 = 348 // struct nlmsghdr 349 "58000000" // length = 88 350 + "1400" // type = SOCK_DIAG_BY_FAMILY 351 + "0200" // flags = NLM_F_MULTI 352 + "00000000" // seqno 353 + "f5220000" // pid 354 // struct inet_diag_msg 355 + "0a" // family = AF_INET6 356 + "01" // idiag_state = 1 357 + "02" // idiag_timer = 2 358 + "ff" // idiag_retrans = 255 359 // inet_diag_sockid 360 + "a817" // idiag_sport = 43031 361 + "960f" // idiag_dport = 38415 362 + "20010db8000000000000000000000001" // idiag_src = 2001:db8::1 363 + "20010db8000000000000000000000002" // idiag_dst = 2001:db8::2 364 + "07000000" // idiag_if = 7 365 + "5800000000000000" // idiag_cookie = 88 366 + "04000000" // idiag_expires = 4 367 + "05000000" // idiag_rqueue = 5 368 + "06000000" // idiag_wqueue = 6 369 + "a3270000" // idiag_uid = 10147 370 + "a57e19f0"; // idiag_inode = 4028202661 371 assertInetDiagMsg1(final NetlinkMessage msg)372 private void assertInetDiagMsg1(final NetlinkMessage msg) { 373 assertNotNull(msg); 374 375 assertTrue(msg instanceof InetDiagMessage); 376 final InetDiagMessage inetDiagMsg = (InetDiagMessage) msg; 377 378 assertNlMsgHdr(inetDiagMsg.getHeader(), 379 NetlinkConstants.SOCK_DIAG_BY_FAMILY, 380 StructNlMsgHdr.NLM_F_MULTI, 381 0 /* seq */, 382 8949 /* pid */); 383 384 assertEquals(AF_INET6, inetDiagMsg.inetDiagMsg.idiag_family); 385 assertEquals(1, inetDiagMsg.inetDiagMsg.idiag_state); 386 assertEquals(2, inetDiagMsg.inetDiagMsg.idiag_timer); 387 assertEquals(255, inetDiagMsg.inetDiagMsg.idiag_retrans); 388 assertInetDiagSockId(inetDiagMsg.inetDiagMsg.id, 389 new InetSocketAddress(InetAddresses.parseNumericAddress("2001:db8::1"), 43031), 390 new InetSocketAddress(InetAddresses.parseNumericAddress("2001:db8::2"), 38415), 391 7 /* ifIndex */, 392 88 /* cookie */); 393 assertEquals(4, inetDiagMsg.inetDiagMsg.idiag_expires); 394 assertEquals(5, inetDiagMsg.inetDiagMsg.idiag_rqueue); 395 assertEquals(6, inetDiagMsg.inetDiagMsg.idiag_wqueue); 396 assertEquals(10147, inetDiagMsg.inetDiagMsg.idiag_uid); 397 assertEquals(4028202661L, inetDiagMsg.inetDiagMsg.idiag_inode); 398 399 // Verify the length of attribute list is 0 as expected since message doesn't 400 // take any attributes 401 assertEquals(0, inetDiagMsg.nlAttrs.size()); 402 } 403 404 // Hexadecimal representation of InetDiagMessage 405 private static final String INET_DIAG_MSG_HEX2 = 406 // struct nlmsghdr 407 "6C000000" // length = 108 408 + "1400" // type = SOCK_DIAG_BY_FAMILY 409 + "0200" // flags = NLM_F_MULTI 410 + "00000000" // seqno 411 + "f5220000" // pid 412 // struct inet_diag_msg 413 + "0a" // family = AF_INET6 414 + "02" // idiag_state = 2 415 + "10" // idiag_timer = 16 416 + "20" // idiag_retrans = 32 417 // inet_diag_sockid 418 + "a845" // idiag_sport = 43077 419 + "01bb" // idiag_dport = 443 420 + "20010db8000000000000000000000003" // idiag_src = 2001:db8::3 421 + "20010db8000000000000000000000004" // idiag_dst = 2001:db8::4 422 + "08000000" // idiag_if = 8 423 + "6300000000000000" // idiag_cookie = 99 424 + "30000000" // idiag_expires = 48 425 + "40000000" // idiag_rqueue = 64 426 + "50000000" // idiag_wqueue = 80 427 + "39300000" // idiag_uid = 12345 428 + "851a0000" // idiag_inode = 6789 429 + "0500" // len = 5 430 + "0800" // type = 8 431 + "00000000" // data 432 + "0800" // len = 8 433 + "0F00" // type = 15(INET_DIAG_MARK) 434 + "850A0C00" // data, socket mark=789125 435 + "0400" // len = 4 436 + "0200"; // type = 2 437 assertInetDiagMsg2(final NetlinkMessage msg)438 private void assertInetDiagMsg2(final NetlinkMessage msg) { 439 assertNotNull(msg); 440 441 assertTrue(msg instanceof InetDiagMessage); 442 final InetDiagMessage inetDiagMsg = (InetDiagMessage) msg; 443 444 assertNlMsgHdr(inetDiagMsg.getHeader(), 445 NetlinkConstants.SOCK_DIAG_BY_FAMILY, 446 StructNlMsgHdr.NLM_F_MULTI, 447 0 /* seq */, 448 8949 /* pid */); 449 450 assertEquals(AF_INET6, inetDiagMsg.inetDiagMsg.idiag_family); 451 assertEquals(2, inetDiagMsg.inetDiagMsg.idiag_state); 452 assertEquals(16, inetDiagMsg.inetDiagMsg.idiag_timer); 453 assertEquals(32, inetDiagMsg.inetDiagMsg.idiag_retrans); 454 assertInetDiagSockId(inetDiagMsg.inetDiagMsg.id, 455 new InetSocketAddress(InetAddresses.parseNumericAddress("2001:db8::3"), 43077), 456 new InetSocketAddress(InetAddresses.parseNumericAddress("2001:db8::4"), 443), 457 8 /* ifIndex */, 458 99 /* cookie */); 459 assertEquals(48, inetDiagMsg.inetDiagMsg.idiag_expires); 460 assertEquals(64, inetDiagMsg.inetDiagMsg.idiag_rqueue); 461 assertEquals(80, inetDiagMsg.inetDiagMsg.idiag_wqueue); 462 assertEquals(12345, inetDiagMsg.inetDiagMsg.idiag_uid); 463 assertEquals(6789, inetDiagMsg.inetDiagMsg.idiag_inode); 464 465 // Verify the number of nlAttr and their content. 466 assertEquals(3, inetDiagMsg.nlAttrs.size()); 467 468 assertEquals(5, inetDiagMsg.nlAttrs.get(0).nla_len); 469 assertEquals(8, inetDiagMsg.nlAttrs.get(0).nla_type); 470 assertArrayEquals( 471 HexEncoding.decode("00".toCharArray(), false), 472 inetDiagMsg.nlAttrs.get(0).nla_value); 473 assertEquals(8, inetDiagMsg.nlAttrs.get(1).nla_len); 474 assertEquals(15, inetDiagMsg.nlAttrs.get(1).nla_type); 475 assertArrayEquals( 476 HexEncoding.decode("850A0C00".toCharArray(), false), 477 inetDiagMsg.nlAttrs.get(1).nla_value); 478 assertEquals(4, inetDiagMsg.nlAttrs.get(2).nla_len); 479 assertEquals(2, inetDiagMsg.nlAttrs.get(2).nla_type); 480 assertNull(inetDiagMsg.nlAttrs.get(2).nla_value); 481 } 482 483 // Hexadecimal representation of InetDiagMessage 484 private static final String INET_DIAG_MSG_HEX_MALFORMED = 485 // struct nlmsghdr 486 "6E000000" // length = 110 487 + "1400" // type = SOCK_DIAG_BY_FAMILY 488 + "0200" // flags = NLM_F_MULTI 489 + "00000000" // seqno 490 + "f5220000" // pid 491 // struct inet_diag_msg 492 + "0a" // family = AF_INET6 493 + "02" // idiag_state = 2 494 + "10" // idiag_timer = 16 495 + "20" // idiag_retrans = 32 496 // inet_diag_sockid 497 + "a845" // idiag_sport = 43077 498 + "01bb" // idiag_dport = 443 499 + "20010db8000000000000000000000005" // idiag_src = 2001:db8::5 500 + "20010db8000000000000000000000006" // idiag_dst = 2001:db8::6 501 + "08000000" // idiag_if = 8 502 + "6300000000000000" // idiag_cookie = 99 503 + "30000000" // idiag_expires = 48 504 + "40000000" // idiag_rqueue = 64 505 + "50000000" // idiag_wqueue = 80 506 + "39300000" // idiag_uid = 12345 507 + "851a0000" // idiag_inode = 6789 508 + "0500" // len = 5 509 + "0800" // type = 8 510 + "00000000" // data 511 + "0800" // len = 8 512 + "0F00" // type = 15(INET_DIAG_MARK) 513 + "850A0C00" // data, socket mark=789125 514 + "0400" // len = 4 515 + "0200" // type = 2 516 + "0100" // len = 1, malformed value 517 + "0100"; // type = 1 518 519 @Test testParseInetDiagResponseMalformedNlAttr()520 public void testParseInetDiagResponseMalformedNlAttr() throws Exception { 521 final ByteBuffer byteBuffer = ByteBuffer.wrap( 522 HexEncoding.decode((INET_DIAG_MSG_HEX_MALFORMED).toCharArray(), false)); 523 byteBuffer.order(ByteOrder.nativeOrder()); 524 assertNull(NetlinkMessage.parse(byteBuffer, NETLINK_INET_DIAG)); 525 } 526 527 // Hexadecimal representation of InetDiagMessage 528 private static final String INET_DIAG_MSG_HEX_TRUNCATED = 529 // struct nlmsghdr 530 "5E000000" // length = 96 531 + "1400" // type = SOCK_DIAG_BY_FAMILY 532 + "0200" // flags = NLM_F_MULTI 533 + "00000000" // seqno 534 + "f5220000" // pid 535 // struct inet_diag_msg 536 + "0a" // family = AF_INET6 537 + "02" // idiag_state = 2 538 + "10" // idiag_timer = 16 539 + "20" // idiag_retrans = 32 540 // inet_diag_sockid 541 + "a845" // idiag_sport = 43077 542 + "01bb" // idiag_dport = 443 543 + "20010db8000000000000000000000005" // idiag_src = 2001:db8::5 544 + "20010db8000000000000000000000006" // idiag_dst = 2001:db8::6 545 + "08000000" // idiag_if = 8 546 + "6300000000000000" // idiag_cookie = 99 547 + "30000000" // idiag_expires = 48 548 + "40000000" // idiag_rqueue = 64 549 + "50000000" // idiag_wqueue = 80 550 + "39300000" // idiag_uid = 12345 551 + "851a0000" // idiag_inode = 6789 552 + "0800" // len = 8 553 + "0100" // type = 1 554 + "000000"; // data, less than the expected length 555 556 @Test testParseInetDiagResponseTruncatedNlAttr()557 public void testParseInetDiagResponseTruncatedNlAttr() throws Exception { 558 final ByteBuffer byteBuffer = ByteBuffer.wrap( 559 HexEncoding.decode((INET_DIAG_MSG_HEX_TRUNCATED).toCharArray(), false)); 560 byteBuffer.order(ByteOrder.nativeOrder()); 561 assertNull(NetlinkMessage.parse(byteBuffer, NETLINK_INET_DIAG)); 562 } 563 564 private static final byte[] INET_DIAG_MSG_BYTES = 565 HexEncoding.decode(INET_DIAG_MSG_HEX1.toCharArray(), false); 566 567 @Test testParseInetDiagResponse()568 public void testParseInetDiagResponse() throws Exception { 569 final ByteBuffer byteBuffer = ByteBuffer.wrap(INET_DIAG_MSG_BYTES); 570 byteBuffer.order(ByteOrder.nativeOrder()); 571 assertInetDiagMsg1(NetlinkMessage.parse(byteBuffer, NETLINK_INET_DIAG)); 572 } 573 574 575 private static final byte[] INET_DIAG_MSG_BYTES_MULTIPLE = 576 HexEncoding.decode((INET_DIAG_MSG_HEX1 + INET_DIAG_MSG_HEX2).toCharArray(), false); 577 578 @Test testParseInetDiagResponseMultiple()579 public void testParseInetDiagResponseMultiple() { 580 final ByteBuffer byteBuffer = ByteBuffer.wrap(INET_DIAG_MSG_BYTES_MULTIPLE); 581 byteBuffer.order(ByteOrder.nativeOrder()); 582 assertInetDiagMsg1(NetlinkMessage.parse(byteBuffer, NETLINK_INET_DIAG)); 583 assertInetDiagMsg2(NetlinkMessage.parse(byteBuffer, NETLINK_INET_DIAG)); 584 } 585 586 private static final String INET_DIAG_SOCK_ID_V4_MAPPED_V6_HEX = 587 "a845" + // idiag_sport = 43077 588 "01bb" + // idiag_dport = 443 589 "00000000000000000000ffffc0000201" + // idiag_src = ::FFFF:192.0.2.1 590 "00000000000000000000ffffc0000202" + // idiag_dst = ::FFFF:192.0.2.2 591 "08000000" + // idiag_if = 8 592 "6300000000000000"; // idiag_cookie = 99 593 594 private static final byte[] INET_DIAG_SOCK_ID_V4_MAPPED_V6_BYTES = 595 HexEncoding.decode(INET_DIAG_SOCK_ID_V4_MAPPED_V6_HEX.toCharArray(), false); 596 597 @Test testParseAndPackInetDiagSockIdV4MappedV6()598 public void testParseAndPackInetDiagSockIdV4MappedV6() { 599 final ByteBuffer parseByteBuffer = ByteBuffer.wrap(INET_DIAG_SOCK_ID_V4_MAPPED_V6_BYTES); 600 parseByteBuffer.order(ByteOrder.nativeOrder()); 601 final StructInetDiagSockId diagSockId = 602 StructInetDiagSockId.parse(parseByteBuffer, (short) AF_INET6); 603 assertNotNull(diagSockId); 604 605 final ByteBuffer packByteBuffer = 606 ByteBuffer.allocate(INET_DIAG_SOCK_ID_V4_MAPPED_V6_BYTES.length); 607 diagSockId.pack(packByteBuffer); 608 609 // Move position to the head since ByteBuffer#equals compares the values from the current 610 // position. 611 parseByteBuffer.position(0); 612 packByteBuffer.position(0); 613 assertEquals(parseByteBuffer, packByteBuffer); 614 } 615 616 // Hexadecimal representation of InetDiagMessage with v4-mapped v6 address 617 private static final String INET_DIAG_MSG_V4_MAPPED_V6_HEX = 618 // struct nlmsghdr 619 "58000000" + // length = 88 620 "1400" + // type = SOCK_DIAG_BY_FAMILY 621 "0200" + // flags = NLM_F_MULTI 622 "00000000" + // seqno 623 "f5220000" + // pid 624 // struct inet_diag_msg 625 "0a" + // family = AF_INET6 626 "01" + // idiag_state = 1 627 "02" + // idiag_timer = 2 628 "03" + // idiag_retrans = 3 629 // inet_diag_sockid 630 "a817" + // idiag_sport = 43031 631 "960f" + // idiag_dport = 38415 632 "00000000000000000000ffffc0000201" + // idiag_src = ::FFFF:192.0.2.1 633 "00000000000000000000ffffc0000202" + // idiag_dst = ::FFFF:192.0.2.2 634 "07000000" + // idiag_if = 7 635 "5800000000000000" + // idiag_cookie = 88 636 "04000000" + // idiag_expires = 4 637 "05000000" + // idiag_rqueue = 5 638 "06000000" + // idiag_wqueue = 6 639 "a3270000" + // idiag_uid = 10147 640 "A57E1900"; // idiag_inode = 1670821 641 642 private static final byte[] INET_DIAG_MSG_V4_MAPPED_V6_BYTES = 643 HexEncoding.decode(INET_DIAG_MSG_V4_MAPPED_V6_HEX.toCharArray(), false); 644 645 @Test testParseInetDiagResponseV4MappedV6()646 public void testParseInetDiagResponseV4MappedV6() throws Exception { 647 final ByteBuffer byteBuffer = ByteBuffer.wrap(INET_DIAG_MSG_V4_MAPPED_V6_BYTES); 648 byteBuffer.order(ByteOrder.nativeOrder()); 649 final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer, NETLINK_INET_DIAG); 650 651 assertNotNull(msg); 652 assertTrue(msg instanceof InetDiagMessage); 653 final InetDiagMessage inetDiagMsg = (InetDiagMessage) msg; 654 final Inet6Address srcAddr = Inet6Address.getByAddress( 655 null /* host */, SRC_V4_MAPPED_V6_ADDRESS_BYTES, -1 /* scope_id */); 656 final Inet6Address dstAddr = Inet6Address.getByAddress( 657 null /* host */, DST_V4_MAPPED_V6_ADDRESS_BYTES, -1 /* scope_id */); 658 assertInetDiagSockId(inetDiagMsg.inetDiagMsg.id, 659 new InetSocketAddress(srcAddr, 43031), 660 new InetSocketAddress(dstAddr, 38415), 661 7 /* ifIndex */, 662 88 /* cookie */); 663 } 664 doTestIsLoopback(InetAddress srcAddr, InetAddress dstAddr, boolean expected)665 private void doTestIsLoopback(InetAddress srcAddr, InetAddress dstAddr, boolean expected) { 666 final InetDiagMessage inetDiagMsg = new InetDiagMessage(new StructNlMsgHdr()); 667 inetDiagMsg.inetDiagMsg.id = new StructInetDiagSockId( 668 new InetSocketAddress(srcAddr, 43031), 669 new InetSocketAddress(dstAddr, 38415) 670 ); 671 672 assertEquals(expected, InetDiagMessage.isLoopback(inetDiagMsg)); 673 } 674 675 @Test testIsLoopback()676 public void testIsLoopback() { 677 doTestIsLoopback( 678 InetAddresses.parseNumericAddress("127.0.0.1"), 679 InetAddresses.parseNumericAddress("192.0.2.1"), 680 true 681 ); 682 doTestIsLoopback( 683 InetAddresses.parseNumericAddress("192.0.2.1"), 684 InetAddresses.parseNumericAddress("127.7.7.7"), 685 true 686 ); 687 doTestIsLoopback( 688 InetAddresses.parseNumericAddress("::1"), 689 InetAddresses.parseNumericAddress("::1"), 690 true 691 ); 692 doTestIsLoopback( 693 InetAddresses.parseNumericAddress("::1"), 694 InetAddresses.parseNumericAddress("2001:db8::1"), 695 true 696 ); 697 } 698 699 @Test testIsLoopbackSameSrcDstAddress()700 public void testIsLoopbackSameSrcDstAddress() { 701 doTestIsLoopback( 702 InetAddresses.parseNumericAddress("192.0.2.1"), 703 InetAddresses.parseNumericAddress("192.0.2.1"), 704 true 705 ); 706 doTestIsLoopback( 707 InetAddresses.parseNumericAddress("2001:db8::1"), 708 InetAddresses.parseNumericAddress("2001:db8::1"), 709 true 710 ); 711 } 712 713 @Test testIsLoopbackNonLoopbackSocket()714 public void testIsLoopbackNonLoopbackSocket() { 715 doTestIsLoopback( 716 InetAddresses.parseNumericAddress("192.0.2.1"), 717 InetAddresses.parseNumericAddress("192.0.2.2"), 718 false 719 ); 720 doTestIsLoopback( 721 InetAddresses.parseNumericAddress("2001:db8::1"), 722 InetAddresses.parseNumericAddress("2001:db8::2"), 723 false 724 ); 725 } 726 727 @Test testIsLoopbackV4MappedV6()728 public void testIsLoopbackV4MappedV6() throws UnknownHostException { 729 // ::FFFF:127.1.2.3 730 final byte[] addrLoopbackByte = { 731 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 732 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 733 (byte) 0x00, (byte) 0x00, (byte) 0xff, (byte) 0xff, 734 (byte) 0x7f, (byte) 0x01, (byte) 0x02, (byte) 0x03, 735 }; 736 // ::FFFF:192.0.2.1 737 final byte[] addrNonLoopbackByte1 = { 738 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 739 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 740 (byte) 0x00, (byte) 0x00, (byte) 0xff, (byte) 0xff, 741 (byte) 0xc0, (byte) 0x00, (byte) 0x02, (byte) 0x01, 742 }; 743 // ::FFFF:192.0.2.2 744 final byte[] addrNonLoopbackByte2 = { 745 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 746 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 747 (byte) 0x00, (byte) 0x00, (byte) 0xff, (byte) 0xff, 748 (byte) 0xc0, (byte) 0x00, (byte) 0x02, (byte) 0x02, 749 }; 750 751 final Inet6Address addrLoopback = Inet6Address.getByAddress(null, addrLoopbackByte, -1); 752 final Inet6Address addrNonLoopback1 = 753 Inet6Address.getByAddress(null, addrNonLoopbackByte1, -1); 754 final Inet6Address addrNonLoopback2 = 755 Inet6Address.getByAddress(null, addrNonLoopbackByte2, -1); 756 757 doTestIsLoopback(addrLoopback, addrNonLoopback1, true); 758 doTestIsLoopback(addrNonLoopback1, addrNonLoopback2, false); 759 doTestIsLoopback(addrNonLoopback1, addrNonLoopback1, true); 760 } 761 doTestContainsUid(final int uid, final Set<Range<Integer>> ranges, final boolean expected)762 private void doTestContainsUid(final int uid, final Set<Range<Integer>> ranges, 763 final boolean expected) { 764 final InetDiagMessage inetDiagMsg = new InetDiagMessage(new StructNlMsgHdr()); 765 inetDiagMsg.inetDiagMsg.idiag_uid = uid; 766 assertEquals(expected, InetDiagMessage.containsUid(inetDiagMsg, ranges)); 767 } 768 769 @Test testContainsUid()770 public void testContainsUid() { 771 doTestContainsUid(77 /* uid */, 772 new ArraySet<>(List.of(new Range<>(0, 100))), 773 true /* expected */); 774 doTestContainsUid(77 /* uid */, 775 new ArraySet<>(List.of(new Range<>(77, 77), new Range<>(100, 200))), 776 true /* expected */); 777 778 doTestContainsUid(77 /* uid */, 779 new ArraySet<>(List.of(new Range<>(100, 200))), 780 false /* expected */); 781 doTestContainsUid(77 /* uid */, 782 new ArraySet<>(List.of(new Range<>(0, 76), new Range<>(78, 100))), 783 false /* expected */); 784 } 785 doTestIsAdbSocket(final int uid, final boolean expected)786 private void doTestIsAdbSocket(final int uid, final boolean expected) { 787 final InetDiagMessage inetDiagMsg = new InetDiagMessage(new StructNlMsgHdr()); 788 inetDiagMsg.inetDiagMsg.idiag_uid = uid; 789 inetDiagMsg.inetDiagMsg.id = new StructInetDiagSockId( 790 new InetSocketAddress(InetAddresses.parseNumericAddress("2001:db8::1"), 38417), 791 new InetSocketAddress(InetAddresses.parseNumericAddress("2001:db8::2"), 38415) 792 ); 793 assertEquals(expected, InetDiagMessage.isAdbSocket(inetDiagMsg)); 794 } 795 796 @Test testIsAdbSocket()797 public void testIsAdbSocket() { 798 final int appUid = 10108; 799 doTestIsAdbSocket(SHELL_UID, true /* expected */); 800 doTestIsAdbSocket(ROOT_UID, false /* expected */); 801 doTestIsAdbSocket(appUid, false /* expected */); 802 } 803 } 804