From 4fc3f4fa152ed9d46af96d86104390528b9b1731 Mon Sep 17 00:00:00 2001 From: Chiachang Wang <chiachangwang@google.com> Date: Fri, 8 Dec 2023 02:00:00 +0000 Subject: [PATCH] Add netlink attributes field into the InetDiagMessage Add nlAttrs parameter to store the remaining attributes data. As a part of follow-up work from aosp/2354202, the TCP socket parsing can be done by using existing InetDiagMessage class. The missing piece in the InetDiagMessage class is the possible netlink attributes fields that may be appended after an InetDiagMessage. Bug: 311119352 Bug: 265877161 Test: atest NetworkStaticLibTests Change-Id: I9c34166124fd4efba2ab211bfb537ccce5e774a4 --- .../module/util/netlink/InetDiagMessage.java | 15 +- .../util/netlink/InetDiagSocketTest.java | 191 ++++++++++++++---- 2 files changed, 165 insertions(+), 41 deletions(-) diff --git a/staticlibs/device/com/android/net/module/util/netlink/InetDiagMessage.java b/staticlibs/device/com/android/net/module/util/netlink/InetDiagMessage.java index 4f76577caa..4bc4266165 100644 --- a/staticlibs/device/com/android/net/module/util/netlink/InetDiagMessage.java +++ b/staticlibs/device/com/android/net/module/util/netlink/InetDiagMessage.java @@ -27,6 +27,7 @@ import static android.system.OsConstants.NETLINK_INET_DIAG; import static com.android.net.module.util.netlink.NetlinkConstants.NLMSG_DONE; import static com.android.net.module.util.netlink.NetlinkConstants.SOCK_DESTROY; import static com.android.net.module.util.netlink.NetlinkConstants.SOCK_DIAG_BY_FAMILY; +import static com.android.net.module.util.netlink.NetlinkConstants.SOCKDIAG_MSG_HEADER_SIZE; import static com.android.net.module.util.netlink.NetlinkConstants.hexify; import static com.android.net.module.util.netlink.NetlinkConstants.stringForAddressFamily; import static com.android.net.module.util.netlink.NetlinkConstants.stringForProtocol; @@ -59,6 +60,7 @@ import java.net.SocketException; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.function.Predicate; @@ -154,7 +156,8 @@ public class InetDiagMessage extends NetlinkMessage { } public StructInetDiagMsg inetDiagMsg; - + // The netlink attributes. + public List<StructNlAttr> nlAttrs = new ArrayList<>(); @VisibleForTesting public InetDiagMessage(@NonNull StructNlMsgHdr header) { super(header); @@ -172,6 +175,16 @@ public class InetDiagMessage extends NetlinkMessage { if (msg.inetDiagMsg == null) { return null; } + final int payloadLength = header.nlmsg_len - SOCKDIAG_MSG_HEADER_SIZE; + final ByteBuffer payload = byteBuffer.slice(); + while (payload.position() < payloadLength) { + final StructNlAttr attr = StructNlAttr.parse(payload); + // Stop parsing for truncated or malformed attribute + if (attr == null) return null; + + msg.nlAttrs.add(attr); + } + return msg; } diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/netlink/InetDiagSocketTest.java b/staticlibs/tests/unit/src/com/android/net/module/util/netlink/InetDiagSocketTest.java index 65e99f8296..b44e428547 100644 --- a/staticlibs/tests/unit/src/com/android/net/module/util/netlink/InetDiagSocketTest.java +++ b/staticlibs/tests/unit/src/com/android/net/module/util/netlink/InetDiagSocketTest.java @@ -32,6 +32,7 @@ import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REQUEST; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -345,28 +346,28 @@ public class InetDiagSocketTest { // Hexadecimal representation of InetDiagMessage private static final String INET_DIAG_MSG_HEX1 = // struct nlmsghdr - "58000000" + // length = 88 - "1400" + // type = SOCK_DIAG_BY_FAMILY - "0200" + // flags = NLM_F_MULTI - "00000000" + // seqno - "f5220000" + // pid + "58000000" // length = 88 + + "1400" // type = SOCK_DIAG_BY_FAMILY + + "0200" // flags = NLM_F_MULTI + + "00000000" // seqno + + "f5220000" // pid // struct inet_diag_msg - "0a" + // family = AF_INET6 - "01" + // idiag_state = 1 - "02" + // idiag_timer = 2 - "ff" + // idiag_retrans = 255 + + "0a" // family = AF_INET6 + + "01" // idiag_state = 1 + + "02" // idiag_timer = 2 + + "ff" // idiag_retrans = 255 // inet_diag_sockid - "a817" + // idiag_sport = 43031 - "960f" + // idiag_dport = 38415 - "20010db8000000000000000000000001" + // idiag_src = 2001:db8::1 - "20010db8000000000000000000000002" + // idiag_dst = 2001:db8::2 - "07000000" + // idiag_if = 7 - "5800000000000000" + // idiag_cookie = 88 - "04000000" + // idiag_expires = 4 - "05000000" + // idiag_rqueue = 5 - "06000000" + // idiag_wqueue = 6 - "a3270000" + // idiag_uid = 10147 - "a57e19f0"; // idiag_inode = 4028202661 + + "a817" // idiag_sport = 43031 + + "960f" // idiag_dport = 38415 + + "20010db8000000000000000000000001" // idiag_src = 2001:db8::1 + + "20010db8000000000000000000000002" // idiag_dst = 2001:db8::2 + + "07000000" // idiag_if = 7 + + "5800000000000000" // idiag_cookie = 88 + + "04000000" // idiag_expires = 4 + + "05000000" // idiag_rqueue = 5 + + "06000000" // idiag_wqueue = 6 + + "a3270000" // idiag_uid = 10147 + + "a57e19f0"; // idiag_inode = 4028202661 private void assertInetDiagMsg1(final NetlinkMessage msg) { assertNotNull(msg); @@ -394,33 +395,45 @@ public class InetDiagSocketTest { assertEquals(6, inetDiagMsg.inetDiagMsg.idiag_wqueue); assertEquals(10147, inetDiagMsg.inetDiagMsg.idiag_uid); assertEquals(4028202661L, inetDiagMsg.inetDiagMsg.idiag_inode); + + // Verify the length of attribute list is 0 as expected since message doesn't + // take any attributes + assertEquals(0, inetDiagMsg.nlAttrs.size()); } // Hexadecimal representation of InetDiagMessage private static final String INET_DIAG_MSG_HEX2 = // struct nlmsghdr - "58000000" + // length = 88 - "1400" + // type = SOCK_DIAG_BY_FAMILY - "0200" + // flags = NLM_F_MULTI - "00000000" + // seqno - "f5220000" + // pid + "6C000000" // length = 108 + + "1400" // type = SOCK_DIAG_BY_FAMILY + + "0200" // flags = NLM_F_MULTI + + "00000000" // seqno + + "f5220000" // pid // struct inet_diag_msg - "0a" + // family = AF_INET6 - "02" + // idiag_state = 2 - "10" + // idiag_timer = 16 - "20" + // idiag_retrans = 32 + + "0a" // family = AF_INET6 + + "02" // idiag_state = 2 + + "10" // idiag_timer = 16 + + "20" // idiag_retrans = 32 // inet_diag_sockid - "a845" + // idiag_sport = 43077 - "01bb" + // idiag_dport = 443 - "20010db8000000000000000000000003" + // idiag_src = 2001:db8::3 - "20010db8000000000000000000000004" + // idiag_dst = 2001:db8::4 - "08000000" + // idiag_if = 8 - "6300000000000000" + // idiag_cookie = 99 - "30000000" + // idiag_expires = 48 - "40000000" + // idiag_rqueue = 64 - "50000000" + // idiag_wqueue = 80 - "39300000" + // idiag_uid = 12345 - "851a0000"; // idiag_inode = 6789 + + "a845" // idiag_sport = 43077 + + "01bb" // idiag_dport = 443 + + "20010db8000000000000000000000003" // idiag_src = 2001:db8::3 + + "20010db8000000000000000000000004" // idiag_dst = 2001:db8::4 + + "08000000" // idiag_if = 8 + + "6300000000000000" // idiag_cookie = 99 + + "30000000" // idiag_expires = 48 + + "40000000" // idiag_rqueue = 64 + + "50000000" // idiag_wqueue = 80 + + "39300000" // idiag_uid = 12345 + + "851a0000" // idiag_inode = 6789 + + "0500" // len = 5 + + "0800" // type = 8 + + "00000000" // data + + "0800" // len = 8 + + "0F00" // type = 15(INET_DIAG_MARK) + + "850A0C00" // data, socket mark=789125 + + "0400" // len = 4 + + "0200"; // type = 2 private void assertInetDiagMsg2(final NetlinkMessage msg) { assertNotNull(msg); @@ -448,6 +461,104 @@ public class InetDiagSocketTest { assertEquals(80, inetDiagMsg.inetDiagMsg.idiag_wqueue); assertEquals(12345, inetDiagMsg.inetDiagMsg.idiag_uid); assertEquals(6789, inetDiagMsg.inetDiagMsg.idiag_inode); + + // Verify the number of nlAttr and their content. + assertEquals(3, inetDiagMsg.nlAttrs.size()); + + assertEquals(5, inetDiagMsg.nlAttrs.get(0).nla_len); + assertEquals(8, inetDiagMsg.nlAttrs.get(0).nla_type); + assertArrayEquals( + HexEncoding.decode("00".toCharArray(), false), + inetDiagMsg.nlAttrs.get(0).nla_value); + assertEquals(8, inetDiagMsg.nlAttrs.get(1).nla_len); + assertEquals(15, inetDiagMsg.nlAttrs.get(1).nla_type); + assertArrayEquals( + HexEncoding.decode("850A0C00".toCharArray(), false), + inetDiagMsg.nlAttrs.get(1).nla_value); + assertEquals(4, inetDiagMsg.nlAttrs.get(2).nla_len); + assertEquals(2, inetDiagMsg.nlAttrs.get(2).nla_type); + assertNull(inetDiagMsg.nlAttrs.get(2).nla_value); + } + + // Hexadecimal representation of InetDiagMessage + private static final String INET_DIAG_MSG_HEX_MALFORMED = + // struct nlmsghdr + "6E000000" // length = 110 + + "1400" // type = SOCK_DIAG_BY_FAMILY + + "0200" // flags = NLM_F_MULTI + + "00000000" // seqno + + "f5220000" // pid + // struct inet_diag_msg + + "0a" // family = AF_INET6 + + "02" // idiag_state = 2 + + "10" // idiag_timer = 16 + + "20" // idiag_retrans = 32 + // inet_diag_sockid + + "a845" // idiag_sport = 43077 + + "01bb" // idiag_dport = 443 + + "20010db8000000000000000000000005" // idiag_src = 2001:db8::5 + + "20010db8000000000000000000000006" // idiag_dst = 2001:db8::6 + + "08000000" // idiag_if = 8 + + "6300000000000000" // idiag_cookie = 99 + + "30000000" // idiag_expires = 48 + + "40000000" // idiag_rqueue = 64 + + "50000000" // idiag_wqueue = 80 + + "39300000" // idiag_uid = 12345 + + "851a0000" // idiag_inode = 6789 + + "0500" // len = 5 + + "0800" // type = 8 + + "00000000" // data + + "0800" // len = 8 + + "0F00" // type = 15(INET_DIAG_MARK) + + "850A0C00" // data, socket mark=789125 + + "0400" // len = 4 + + "0200" // type = 2 + + "0100" // len = 1, malformed value + + "0100"; // type = 1 + + @Test + public void testParseInetDiagResponseMalformedNlAttr() throws Exception { + final ByteBuffer byteBuffer = ByteBuffer.wrap( + HexEncoding.decode((INET_DIAG_MSG_HEX_MALFORMED).toCharArray(), false)); + byteBuffer.order(ByteOrder.nativeOrder()); + assertNull(NetlinkMessage.parse(byteBuffer, NETLINK_INET_DIAG)); + } + + // Hexadecimal representation of InetDiagMessage + private static final String INET_DIAG_MSG_HEX_TRUNCATED = + // struct nlmsghdr + "5E000000" // length = 96 + + "1400" // type = SOCK_DIAG_BY_FAMILY + + "0200" // flags = NLM_F_MULTI + + "00000000" // seqno + + "f5220000" // pid + // struct inet_diag_msg + + "0a" // family = AF_INET6 + + "02" // idiag_state = 2 + + "10" // idiag_timer = 16 + + "20" // idiag_retrans = 32 + // inet_diag_sockid + + "a845" // idiag_sport = 43077 + + "01bb" // idiag_dport = 443 + + "20010db8000000000000000000000005" // idiag_src = 2001:db8::5 + + "20010db8000000000000000000000006" // idiag_dst = 2001:db8::6 + + "08000000" // idiag_if = 8 + + "6300000000000000" // idiag_cookie = 99 + + "30000000" // idiag_expires = 48 + + "40000000" // idiag_rqueue = 64 + + "50000000" // idiag_wqueue = 80 + + "39300000" // idiag_uid = 12345 + + "851a0000" // idiag_inode = 6789 + + "0800" // len = 8 + + "0100" // type = 1 + + "000000"; // data, less than the expected length + + @Test + public void testParseInetDiagResponseTruncatedNlAttr() throws Exception { + final ByteBuffer byteBuffer = ByteBuffer.wrap( + HexEncoding.decode((INET_DIAG_MSG_HEX_TRUNCATED).toCharArray(), false)); + byteBuffer.order(ByteOrder.nativeOrder()); + assertNull(NetlinkMessage.parse(byteBuffer, NETLINK_INET_DIAG)); } private static final byte[] INET_DIAG_MSG_BYTES = -- GitLab