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