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 android.net.netlink; 18 19 import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP; 20 import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST; 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 org.junit.Assert.assertArrayEquals; 28 import static org.junit.Assert.assertEquals; 29 import static org.junit.Assert.assertNotNull; 30 import static org.junit.Assert.assertTrue; 31 import static org.junit.Assert.fail; 32 33 import androidx.test.filters.SmallTest; 34 import androidx.test.runner.AndroidJUnit4; 35 36 import libcore.util.HexEncoding; 37 38 import org.junit.Test; 39 import org.junit.runner.RunWith; 40 41 import java.net.InetAddress; 42 import java.net.InetSocketAddress; 43 import java.nio.ByteBuffer; 44 import java.nio.ByteOrder; 45 46 @RunWith(AndroidJUnit4.class) 47 @SmallTest 48 public class InetDiagSocketTest { 49 // Hexadecimal representation of InetDiagReqV2 request. 50 private static final String INET_DIAG_REQ_V2_UDP_INET4_HEX = 51 // struct nlmsghdr 52 "48000000" + // length = 72 53 "1400" + // type = SOCK_DIAG_BY_FAMILY 54 "0103" + // flags = NLM_F_REQUEST | NLM_F_DUMP 55 "00000000" + // seqno 56 "00000000" + // pid (0 == kernel) 57 // struct inet_diag_req_v2 58 "02" + // family = AF_INET 59 "11" + // protcol = IPPROTO_UDP 60 "00" + // idiag_ext 61 "00" + // pad 62 "ffffffff" + // idiag_states 63 // inet_diag_sockid 64 "a5de" + // idiag_sport = 42462 65 "b971" + // idiag_dport = 47473 66 "0a006402000000000000000000000000" + // idiag_src = 10.0.100.2 67 "08080808000000000000000000000000" + // idiag_dst = 8.8.8.8 68 "00000000" + // idiag_if 69 "ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE 70 private static final byte[] INET_DIAG_REQ_V2_UDP_INET4_BYTES = 71 HexEncoding.decode(INET_DIAG_REQ_V2_UDP_INET4_HEX.toCharArray(), false); 72 73 @Test testInetDiagReqV2UdpInet4()74 public void testInetDiagReqV2UdpInet4() throws Exception { 75 InetSocketAddress local = new InetSocketAddress(InetAddress.getByName("10.0.100.2"), 76 42462); 77 InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"), 78 47473); 79 final byte[] msg = InetDiagMessage.InetDiagReqV2(IPPROTO_UDP, local, remote, AF_INET, 80 (short) (NLM_F_REQUEST | NLM_F_DUMP)); 81 assertArrayEquals(INET_DIAG_REQ_V2_UDP_INET4_BYTES, msg); 82 } 83 84 // Hexadecimal representation of InetDiagReqV2 request. 85 private static final String INET_DIAG_REQ_V2_TCP_INET6_HEX = 86 // struct nlmsghdr 87 "48000000" + // length = 72 88 "1400" + // type = SOCK_DIAG_BY_FAMILY 89 "0100" + // flags = NLM_F_REQUEST 90 "00000000" + // seqno 91 "00000000" + // pid (0 == kernel) 92 // struct inet_diag_req_v2 93 "0a" + // family = AF_INET6 94 "06" + // protcol = IPPROTO_TCP 95 "00" + // idiag_ext 96 "00" + // pad 97 "ffffffff" + // idiag_states 98 // inet_diag_sockid 99 "a5de" + // idiag_sport = 42462 100 "b971" + // idiag_dport = 47473 101 "fe8000000000000086c9b2fffe6aed4b" + // idiag_src = fe80::86c9:b2ff:fe6a:ed4b 102 "08080808000000000000000000000000" + // idiag_dst = 8.8.8.8 103 "00000000" + // idiag_if 104 "ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE 105 private static final byte[] INET_DIAG_REQ_V2_TCP_INET6_BYTES = 106 HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET6_HEX.toCharArray(), false); 107 108 @Test testInetDiagReqV2TcpInet6()109 public void testInetDiagReqV2TcpInet6() throws Exception { 110 InetSocketAddress local = new InetSocketAddress( 111 InetAddress.getByName("fe80::86c9:b2ff:fe6a:ed4b"), 42462); 112 InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"), 113 47473); 114 byte[] msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET6, 115 NLM_F_REQUEST); 116 117 assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_BYTES, msg); 118 } 119 120 // Hexadecimal representation of InetDiagReqV2 request with extension, INET_DIAG_INFO. 121 private static final String INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_HEX = 122 // struct nlmsghdr 123 "48000000" + // length = 72 124 "1400" + // type = SOCK_DIAG_BY_FAMILY 125 "0100" + // flags = NLM_F_REQUEST 126 "00000000" + // seqno 127 "00000000" + // pid (0 == kernel) 128 // struct inet_diag_req_v2 129 "02" + // family = AF_INET 130 "06" + // protcol = IPPROTO_TCP 131 "02" + // idiag_ext = INET_DIAG_INFO 132 "00" + // pad 133 "ffffffff" + // idiag_states 134 // inet_diag_sockid 135 "3039" + // idiag_sport = 12345 136 "d431" + // idiag_dport = 54321 137 "01020304000000000000000000000000" + // idiag_src = 1.2.3.4 138 "08080404000000000000000000000000" + // idiag_dst = 8.8.4.4 139 "00000000" + // idiag_if 140 "ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE 141 142 private static final byte[] INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_BYTES = 143 HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_HEX.toCharArray(), false); 144 private static final int TCP_ALL_STATES = 0xffffffff; 145 @Test testInetDiagReqV2TcpInetWithExt()146 public void testInetDiagReqV2TcpInetWithExt() throws Exception { 147 InetSocketAddress local = new InetSocketAddress( 148 InetAddress.getByName("1.2.3.4"), 12345); 149 InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.4.4"), 150 54321); 151 byte[] msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET, 152 NLM_F_REQUEST, 0 /* pad */, 2 /* idiagExt */, TCP_ALL_STATES); 153 154 assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_BYTES, msg); 155 156 local = new InetSocketAddress( 157 InetAddress.getByName("fe80::86c9:b2ff:fe6a:ed4b"), 42462); 158 remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"), 159 47473); 160 msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET6, 161 NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES); 162 163 assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_BYTES, msg); 164 } 165 166 // Hexadecimal representation of InetDiagReqV2 request with no socket specified. 167 private static final String INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFIED_HEX = 168 // struct nlmsghdr 169 "48000000" + // length = 72 170 "1400" + // type = SOCK_DIAG_BY_FAMILY 171 "0100" + // flags = NLM_F_REQUEST 172 "00000000" + // seqno 173 "00000000" + // pid (0 == kernel) 174 // struct inet_diag_req_v2 175 "0a" + // family = AF_INET6 176 "06" + // protcol = IPPROTO_TCP 177 "00" + // idiag_ext 178 "00" + // pad 179 "ffffffff" + // idiag_states 180 // inet_diag_sockid 181 "0000" + // idiag_sport 182 "0000" + // idiag_dport 183 "00000000000000000000000000000000" + // idiag_src 184 "00000000000000000000000000000000" + // idiag_dst 185 "00000000" + // idiag_if 186 "0000000000000000"; // idiag_cookie 187 188 private static final byte[] INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFED_BYTES = 189 HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFIED_HEX.toCharArray(), false); 190 191 @Test testInetDiagReqV2TcpInet6NoIdSpecified()192 public void testInetDiagReqV2TcpInet6NoIdSpecified() throws Exception { 193 InetSocketAddress local = new InetSocketAddress( 194 InetAddress.getByName("fe80::fe6a:ed4b"), 12345); 195 InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.4.4"), 196 54321); 197 // Verify no socket specified if either local or remote socket address is null. 198 byte[] msgExt = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, null, null, AF_INET6, 199 NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES); 200 byte[] msg; 201 try { 202 msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, null, remote, AF_INET6, 203 NLM_F_REQUEST); 204 fail("Both remote and local should be null, expected UnknownHostException"); 205 } catch (NullPointerException e) { 206 } 207 208 try { 209 msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, null, AF_INET6, 210 NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES); 211 fail("Both remote and local should be null, expected UnknownHostException"); 212 } catch (NullPointerException e) { 213 } 214 215 msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, null, null, AF_INET6, 216 NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES); 217 assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFED_BYTES, msg); 218 assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFED_BYTES, msgExt); 219 } 220 221 // Hexadecimal representation of InetDiagReqV2 request. 222 private static final String INET_DIAG_MSG_HEX = 223 // struct nlmsghdr 224 "58000000" + // length = 88 225 "1400" + // type = SOCK_DIAG_BY_FAMILY 226 "0200" + // flags = NLM_F_MULTI 227 "00000000" + // seqno 228 "f5220000" + // pid (0 == kernel) 229 // struct inet_diag_msg 230 "0a" + // family = AF_INET6 231 "01" + // idiag_state 232 "00" + // idiag_timer 233 "00" + // idiag_retrans 234 // inet_diag_sockid 235 "a817" + // idiag_sport = 43031 236 "960f" + // idiag_dport = 38415 237 "fe8000000000000086c9b2fffe6aed4b" + // idiag_src = fe80::86c9:b2ff:fe6a:ed4b 238 "00000000000000000000ffff08080808" + // idiag_dst = 8.8.8.8 239 "00000000" + // idiag_if 240 "ffffffffffffffff" + // idiag_cookie = INET_DIAG_NOCOOKIE 241 "00000000" + // idiag_expires 242 "00000000" + // idiag_rqueue 243 "00000000" + // idiag_wqueue 244 "a3270000" + // idiag_uid 245 "A57E1900"; // idiag_inode 246 private static final byte[] INET_DIAG_MSG_BYTES = 247 HexEncoding.decode(INET_DIAG_MSG_HEX.toCharArray(), false); 248 249 @Test testParseInetDiagResponse()250 public void testParseInetDiagResponse() throws Exception { 251 final ByteBuffer byteBuffer = ByteBuffer.wrap(INET_DIAG_MSG_BYTES); 252 byteBuffer.order(ByteOrder.LITTLE_ENDIAN); 253 final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer, NETLINK_INET_DIAG); 254 assertNotNull(msg); 255 256 assertTrue(msg instanceof InetDiagMessage); 257 final InetDiagMessage inetDiagMsg = (InetDiagMessage) msg; 258 assertEquals(10147, inetDiagMsg.mStructInetDiagMsg.idiag_uid); 259 260 final StructNlMsgHdr hdr = inetDiagMsg.getHeader(); 261 assertNotNull(hdr); 262 assertEquals(NetlinkConstants.SOCK_DIAG_BY_FAMILY, hdr.nlmsg_type); 263 assertEquals(StructNlMsgHdr.NLM_F_MULTI, hdr.nlmsg_flags); 264 assertEquals(0, hdr.nlmsg_seq); 265 assertEquals(8949, hdr.nlmsg_pid); 266 } 267 } 268