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