Loading common/netlinkclient/src/android/net/netlink/NetlinkMessage.java +2 −4 Original line number Diff line number Diff line Loading @@ -70,11 +70,9 @@ public class NetlinkMessage { // not constant. if (nlFamily == OsConstants.NETLINK_ROUTE) { return parseRtMessage(nlmsghdr, byteBuffer); } if (nlFamily == OsConstants.NETLINK_INET_DIAG) { } else if (nlFamily == OsConstants.NETLINK_INET_DIAG) { return parseInetDiagMessage(nlmsghdr, byteBuffer); } if (nlFamily == OsConstants.NETLINK_NETFILTER) { } else if (nlFamily == OsConstants.NETLINK_NETFILTER) { return parseNfMessage(nlmsghdr, byteBuffer); } Loading common/netlinkclient/src/android/net/netlink/StructNlMsgHdr.java +5 −2 Original line number Diff line number Diff line Loading @@ -47,7 +47,8 @@ public class StructNlMsgHdr { public static final short NLM_F_CREATE = 0x400; public static final short NLM_F_APPEND = 0x800; // TODO: Probably need to distinguish the flags which have the same value. For example, // NLM_F_MATCH (0x200) and NLM_F_EXCL (0x200). public static String stringForNlMsgFlags(short flags) { final StringBuilder sb = new StringBuilder(); if ((flags & NLM_F_REQUEST) != 0) { Loading Loading @@ -133,7 +134,9 @@ public class StructNlMsgHdr { /** * Transform a netlink header into a string. The netlink family is required for transforming * a netlink type integer into a string. * @param nlFamily netlink family. * @param nlFamily netlink family. Using Integer will not incur autoboxing penalties because * family values are small, and all Integer objects between -128 and 127 are * statically cached. See Integer.IntegerCache. * @return A list of header elements. */ @NonNull Loading tests/unit/src/android/net/ip/ConntrackMonitorTest.java 0 → 100644 +153 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.net.ip; import static android.system.OsConstants.AF_UNIX; import static android.system.OsConstants.SOCK_DGRAM; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.verify; import android.net.netlink.NetlinkSocket; import android.net.util.SharedLog; import android.os.ConditionVariable; import android.os.Handler; import android.os.HandlerThread; import android.system.ErrnoException; import android.system.Os; import androidx.annotation.NonNull; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import libcore.util.HexEncoding; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.io.FileDescriptor; import java.io.InterruptedIOException; /** * Tests for ConntrackMonitor. */ @RunWith(AndroidJUnit4.class) @SmallTest public class ConntrackMonitorTest { private static final long TIMEOUT_MS = 10_000L; @Mock private SharedLog mLog; @Mock private ConntrackMonitor.ConntrackEventConsumer mConsumer; private final HandlerThread mHandlerThread = new HandlerThread( ConntrackMonitorTest.class.getSimpleName()); // Late init since the handler thread has been started. private Handler mHandler; private TestConntrackMonitor mConntrackMonitor; // A version of [ConntrackMonitor] that reads packets from the socket pair, and instead // allows the test to write test packets to the socket pair via [sendMessage]. private class TestConntrackMonitor extends ConntrackMonitor { TestConntrackMonitor(@NonNull Handler h, @NonNull SharedLog log, @NonNull ConntrackEventConsumer cb) { super(h, log, cb); mReadFd = new FileDescriptor(); mWriteFd = new FileDescriptor(); try { Os.socketpair(AF_UNIX, SOCK_DGRAM, 0, mWriteFd, mReadFd); } catch (ErrnoException e) { fail("Could not create socket pair: " + e); } } @Override protected FileDescriptor createFd() { return mReadFd; } private void sendMessage(byte[] msg) { mHandler.post(() -> { try { NetlinkSocket.sendMessage(mWriteFd, msg, 0 /* offset */, msg.length, TIMEOUT_MS); } catch (ErrnoException | InterruptedIOException e) { fail("Unable to send netfilter message: " + e); } }); } private final FileDescriptor mReadFd; private final FileDescriptor mWriteFd; } @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mHandlerThread.start(); mHandler = new Handler(mHandlerThread.getLooper()); // ConntrackMonitor needs to be started from the handler thread. final ConditionVariable initDone = new ConditionVariable(); mHandler.post(() -> { TestConntrackMonitor m = new TestConntrackMonitor(mHandler, mLog, mConsumer); m.start(); mConntrackMonitor = m; initDone.open(); }); if (!initDone.block(TIMEOUT_MS)) { fail("... init monitor timed-out after " + TIMEOUT_MS + "ms"); } } @After public void tearDown() throws Exception { mHandlerThread.quitSafely(); } // TODO: Add conntrack message attributes to have further verification. public static final String CT_V4NEW_HEX = // CHECKSTYLE:OFF IndentationCheck // struct nlmsghdr "14000000" + // length = 20 "0001" + // type = NFNL_SUBSYS_CTNETLINK (1) << 8 | IPCTNL_MSG_CT_NEW (0) "0006" + // flags = NLM_F_CREATE | NLM_F_EXCL "00000000" + // seqno = 0 "00000000" + // pid = 0 // struct nfgenmsg "02" + // nfgen_family = AF_INET "00" + // version = NFNETLINK_V0 "0000"; // res_id // CHECKSTYLE:ON IndentationCheck public static final byte[] CT_V4NEW_BYTES = HexEncoding.decode(CT_V4NEW_HEX.replaceAll(" ", "").toCharArray(), false); @Test public void testConntrackEvent_New() throws Exception { mConntrackMonitor.sendMessage(CT_V4NEW_BYTES); verify(mConsumer, timeout(TIMEOUT_MS)).accept(any() /* TODO: check the content */); } } tests/unit/src/android/net/netlink/NetlinkConstantsTest.java 0 → 100644 +131 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.net.netlink; import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_DELETE; import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_GET; import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_GET_CTRZERO; import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_GET_DYING; import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_GET_STATS; import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_GET_STATS_CPU; import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_GET_UNCONFIRMED; import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_NEW; import static android.net.netlink.NetlinkConstants.NFNL_SUBSYS_CTNETLINK; import static android.net.netlink.NetlinkConstants.NLMSG_DONE; import static android.net.netlink.NetlinkConstants.NLMSG_ERROR; import static android.net.netlink.NetlinkConstants.NLMSG_NOOP; import static android.net.netlink.NetlinkConstants.NLMSG_OVERRUN; import static android.net.netlink.NetlinkConstants.RTM_DELADDR; import static android.net.netlink.NetlinkConstants.RTM_DELLINK; import static android.net.netlink.NetlinkConstants.RTM_DELNEIGH; import static android.net.netlink.NetlinkConstants.RTM_DELROUTE; import static android.net.netlink.NetlinkConstants.RTM_DELRULE; import static android.net.netlink.NetlinkConstants.RTM_GETADDR; import static android.net.netlink.NetlinkConstants.RTM_GETLINK; import static android.net.netlink.NetlinkConstants.RTM_GETNEIGH; import static android.net.netlink.NetlinkConstants.RTM_GETROUTE; import static android.net.netlink.NetlinkConstants.RTM_GETRULE; import static android.net.netlink.NetlinkConstants.RTM_NEWADDR; import static android.net.netlink.NetlinkConstants.RTM_NEWLINK; import static android.net.netlink.NetlinkConstants.RTM_NEWNDUSEROPT; import static android.net.netlink.NetlinkConstants.RTM_NEWNEIGH; import static android.net.netlink.NetlinkConstants.RTM_NEWROUTE; import static android.net.netlink.NetlinkConstants.RTM_NEWRULE; import static android.net.netlink.NetlinkConstants.RTM_SETLINK; import static android.net.netlink.NetlinkConstants.SOCK_DIAG_BY_FAMILY; import static android.net.netlink.NetlinkConstants.stringForNlMsgType; import static android.system.OsConstants.NETLINK_INET_DIAG; import static android.system.OsConstants.NETLINK_NETFILTER; import static android.system.OsConstants.NETLINK_ROUTE; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) @SmallTest public class NetlinkConstantsTest { private static final short UNKNOWN_FAMILY = 1234; private short makeCtType(short msgType) { return (short) (NFNL_SUBSYS_CTNETLINK << 8 | (byte) msgType); } @Test public void testStringForNlMsgType() { assertEquals("RTM_NEWLINK", stringForNlMsgType(RTM_NEWLINK, NETLINK_ROUTE)); assertEquals("RTM_DELLINK", stringForNlMsgType(RTM_DELLINK, NETLINK_ROUTE)); assertEquals("RTM_GETLINK", stringForNlMsgType(RTM_GETLINK, NETLINK_ROUTE)); assertEquals("RTM_SETLINK", stringForNlMsgType(RTM_SETLINK, NETLINK_ROUTE)); assertEquals("RTM_NEWADDR", stringForNlMsgType(RTM_NEWADDR, NETLINK_ROUTE)); assertEquals("RTM_DELADDR", stringForNlMsgType(RTM_DELADDR, NETLINK_ROUTE)); assertEquals("RTM_GETADDR", stringForNlMsgType(RTM_GETADDR, NETLINK_ROUTE)); assertEquals("RTM_NEWROUTE", stringForNlMsgType(RTM_NEWROUTE, NETLINK_ROUTE)); assertEquals("RTM_DELROUTE", stringForNlMsgType(RTM_DELROUTE, NETLINK_ROUTE)); assertEquals("RTM_GETROUTE", stringForNlMsgType(RTM_GETROUTE, NETLINK_ROUTE)); assertEquals("RTM_NEWNEIGH", stringForNlMsgType(RTM_NEWNEIGH, NETLINK_ROUTE)); assertEquals("RTM_DELNEIGH", stringForNlMsgType(RTM_DELNEIGH, NETLINK_ROUTE)); assertEquals("RTM_GETNEIGH", stringForNlMsgType(RTM_GETNEIGH, NETLINK_ROUTE)); assertEquals("RTM_NEWRULE", stringForNlMsgType(RTM_NEWRULE, NETLINK_ROUTE)); assertEquals("RTM_DELRULE", stringForNlMsgType(RTM_DELRULE, NETLINK_ROUTE)); assertEquals("RTM_GETRULE", stringForNlMsgType(RTM_GETRULE, NETLINK_ROUTE)); assertEquals("RTM_NEWNDUSEROPT", stringForNlMsgType(RTM_NEWNDUSEROPT, NETLINK_ROUTE)); assertEquals("SOCK_DIAG_BY_FAMILY", stringForNlMsgType(SOCK_DIAG_BY_FAMILY, NETLINK_INET_DIAG)); assertEquals("IPCTNL_MSG_CT_NEW", stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_NEW), NETLINK_NETFILTER)); assertEquals("IPCTNL_MSG_CT_GET", stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_GET), NETLINK_NETFILTER)); assertEquals("IPCTNL_MSG_CT_DELETE", stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_DELETE), NETLINK_NETFILTER)); assertEquals("IPCTNL_MSG_CT_GET_CTRZERO", stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_GET_CTRZERO), NETLINK_NETFILTER)); assertEquals("IPCTNL_MSG_CT_GET_STATS_CPU", stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_GET_STATS_CPU), NETLINK_NETFILTER)); assertEquals("IPCTNL_MSG_CT_GET_STATS", stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_GET_STATS), NETLINK_NETFILTER)); assertEquals("IPCTNL_MSG_CT_GET_DYING", stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_GET_DYING), NETLINK_NETFILTER)); assertEquals("IPCTNL_MSG_CT_GET_UNCONFIRMED", stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_GET_UNCONFIRMED), NETLINK_NETFILTER)); } @Test public void testStringForNlMsgType_ControlMessage() { for (int family : new int[]{NETLINK_ROUTE, NETLINK_INET_DIAG, NETLINK_NETFILTER}) { assertEquals("NLMSG_NOOP", stringForNlMsgType(NLMSG_NOOP, family)); assertEquals("NLMSG_ERROR", stringForNlMsgType(NLMSG_ERROR, family)); assertEquals("NLMSG_DONE", stringForNlMsgType(NLMSG_DONE, family)); assertEquals("NLMSG_OVERRUN", stringForNlMsgType(NLMSG_OVERRUN, family)); } } @Test public void testStringForNlMsgType_UnknownFamily() { assertTrue(stringForNlMsgType(RTM_NEWLINK, UNKNOWN_FAMILY).startsWith("unknown")); assertTrue(stringForNlMsgType(SOCK_DIAG_BY_FAMILY, UNKNOWN_FAMILY).startsWith("unknown")); assertTrue(stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_NEW), UNKNOWN_FAMILY) .startsWith("unknown")); } } tests/unit/src/android/net/netlink/StructNlMsgHdrTest.java 0 → 100644 +102 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.net.netlink; import static org.junit.Assert.fail; import android.system.OsConstants; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) @SmallTest public class StructNlMsgHdrTest { public static final short TEST_NLMSG_LEN = 16; public static final short TEST_NLMSG_FLAGS = StructNlMsgHdr.NLM_F_REQUEST | StructNlMsgHdr.NLM_F_MULTI | StructNlMsgHdr.NLM_F_ACK | StructNlMsgHdr.NLM_F_ECHO; public static final short TEST_NLMSG_SEQ = 1234; public static final short TEST_NLMSG_PID = 5678; // Checking the header string nlmsg_{len, ..} of the number can make sure that the checking // number comes from the expected element. // TODO: Verify more flags once StructNlMsgHdr can distinguish the flags which have the same // value. For example, NLM_F_MATCH (0x200) and NLM_F_EXCL (0x200) can't be distinguished. // See StructNlMsgHdrTest#stringForNlMsgFlags. public static final String TEST_NLMSG_LEN_STR = "nlmsg_len{16}"; public static final String TEST_NLMSG_FLAGS_STR = "NLM_F_REQUEST|NLM_F_MULTI|NLM_F_ACK|NLM_F_ECHO"; public static final String TEST_NLMSG_SEQ_STR = "nlmsg_seq{1234}"; public static final String TEST_NLMSG_PID_STR = "nlmsg_pid{5678}"; private StructNlMsgHdr makeStructNlMsgHdr(short type) { final StructNlMsgHdr struct = new StructNlMsgHdr(); struct.nlmsg_len = TEST_NLMSG_LEN; struct.nlmsg_type = type; struct.nlmsg_flags = TEST_NLMSG_FLAGS; struct.nlmsg_seq = TEST_NLMSG_SEQ; struct.nlmsg_pid = TEST_NLMSG_PID; return struct; } private static void assertContains(String actualValue, String expectedSubstring) { if (actualValue.contains(expectedSubstring)) return; fail("\"" + actualValue + "\" does not contain \"" + expectedSubstring + "\""); } @Test public void testToString() { StructNlMsgHdr struct = makeStructNlMsgHdr(NetlinkConstants.RTM_NEWADDR); String s = struct.toString(); assertContains(s, TEST_NLMSG_LEN_STR); assertContains(s, TEST_NLMSG_FLAGS_STR); assertContains(s, TEST_NLMSG_SEQ_STR); assertContains(s, TEST_NLMSG_PID_STR); assertContains(s, "nlmsg_type{20()}"); struct = makeStructNlMsgHdr(NetlinkConstants.SOCK_DIAG_BY_FAMILY); s = struct.toString(); assertContains(s, TEST_NLMSG_LEN_STR); assertContains(s, TEST_NLMSG_FLAGS_STR); assertContains(s, TEST_NLMSG_SEQ_STR); assertContains(s, TEST_NLMSG_PID_STR); assertContains(s, "nlmsg_type{20()}"); } @Test public void testToStringWithNetlinkFamily() { StructNlMsgHdr struct = makeStructNlMsgHdr(NetlinkConstants.RTM_NEWADDR); String s = struct.toString(OsConstants.NETLINK_ROUTE); assertContains(s, TEST_NLMSG_LEN_STR); assertContains(s, TEST_NLMSG_FLAGS_STR); assertContains(s, TEST_NLMSG_SEQ_STR); assertContains(s, TEST_NLMSG_PID_STR); assertContains(s, "nlmsg_type{20(RTM_NEWADDR)}"); struct = makeStructNlMsgHdr(NetlinkConstants.SOCK_DIAG_BY_FAMILY); s = struct.toString(OsConstants.NETLINK_INET_DIAG); assertContains(s, TEST_NLMSG_LEN_STR); assertContains(s, TEST_NLMSG_FLAGS_STR); assertContains(s, TEST_NLMSG_SEQ_STR); assertContains(s, TEST_NLMSG_PID_STR); assertContains(s, "nlmsg_type{20(SOCK_DIAG_BY_FAMILY)}"); } } Loading
common/netlinkclient/src/android/net/netlink/NetlinkMessage.java +2 −4 Original line number Diff line number Diff line Loading @@ -70,11 +70,9 @@ public class NetlinkMessage { // not constant. if (nlFamily == OsConstants.NETLINK_ROUTE) { return parseRtMessage(nlmsghdr, byteBuffer); } if (nlFamily == OsConstants.NETLINK_INET_DIAG) { } else if (nlFamily == OsConstants.NETLINK_INET_DIAG) { return parseInetDiagMessage(nlmsghdr, byteBuffer); } if (nlFamily == OsConstants.NETLINK_NETFILTER) { } else if (nlFamily == OsConstants.NETLINK_NETFILTER) { return parseNfMessage(nlmsghdr, byteBuffer); } Loading
common/netlinkclient/src/android/net/netlink/StructNlMsgHdr.java +5 −2 Original line number Diff line number Diff line Loading @@ -47,7 +47,8 @@ public class StructNlMsgHdr { public static final short NLM_F_CREATE = 0x400; public static final short NLM_F_APPEND = 0x800; // TODO: Probably need to distinguish the flags which have the same value. For example, // NLM_F_MATCH (0x200) and NLM_F_EXCL (0x200). public static String stringForNlMsgFlags(short flags) { final StringBuilder sb = new StringBuilder(); if ((flags & NLM_F_REQUEST) != 0) { Loading Loading @@ -133,7 +134,9 @@ public class StructNlMsgHdr { /** * Transform a netlink header into a string. The netlink family is required for transforming * a netlink type integer into a string. * @param nlFamily netlink family. * @param nlFamily netlink family. Using Integer will not incur autoboxing penalties because * family values are small, and all Integer objects between -128 and 127 are * statically cached. See Integer.IntegerCache. * @return A list of header elements. */ @NonNull Loading
tests/unit/src/android/net/ip/ConntrackMonitorTest.java 0 → 100644 +153 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.net.ip; import static android.system.OsConstants.AF_UNIX; import static android.system.OsConstants.SOCK_DGRAM; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.verify; import android.net.netlink.NetlinkSocket; import android.net.util.SharedLog; import android.os.ConditionVariable; import android.os.Handler; import android.os.HandlerThread; import android.system.ErrnoException; import android.system.Os; import androidx.annotation.NonNull; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import libcore.util.HexEncoding; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.io.FileDescriptor; import java.io.InterruptedIOException; /** * Tests for ConntrackMonitor. */ @RunWith(AndroidJUnit4.class) @SmallTest public class ConntrackMonitorTest { private static final long TIMEOUT_MS = 10_000L; @Mock private SharedLog mLog; @Mock private ConntrackMonitor.ConntrackEventConsumer mConsumer; private final HandlerThread mHandlerThread = new HandlerThread( ConntrackMonitorTest.class.getSimpleName()); // Late init since the handler thread has been started. private Handler mHandler; private TestConntrackMonitor mConntrackMonitor; // A version of [ConntrackMonitor] that reads packets from the socket pair, and instead // allows the test to write test packets to the socket pair via [sendMessage]. private class TestConntrackMonitor extends ConntrackMonitor { TestConntrackMonitor(@NonNull Handler h, @NonNull SharedLog log, @NonNull ConntrackEventConsumer cb) { super(h, log, cb); mReadFd = new FileDescriptor(); mWriteFd = new FileDescriptor(); try { Os.socketpair(AF_UNIX, SOCK_DGRAM, 0, mWriteFd, mReadFd); } catch (ErrnoException e) { fail("Could not create socket pair: " + e); } } @Override protected FileDescriptor createFd() { return mReadFd; } private void sendMessage(byte[] msg) { mHandler.post(() -> { try { NetlinkSocket.sendMessage(mWriteFd, msg, 0 /* offset */, msg.length, TIMEOUT_MS); } catch (ErrnoException | InterruptedIOException e) { fail("Unable to send netfilter message: " + e); } }); } private final FileDescriptor mReadFd; private final FileDescriptor mWriteFd; } @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mHandlerThread.start(); mHandler = new Handler(mHandlerThread.getLooper()); // ConntrackMonitor needs to be started from the handler thread. final ConditionVariable initDone = new ConditionVariable(); mHandler.post(() -> { TestConntrackMonitor m = new TestConntrackMonitor(mHandler, mLog, mConsumer); m.start(); mConntrackMonitor = m; initDone.open(); }); if (!initDone.block(TIMEOUT_MS)) { fail("... init monitor timed-out after " + TIMEOUT_MS + "ms"); } } @After public void tearDown() throws Exception { mHandlerThread.quitSafely(); } // TODO: Add conntrack message attributes to have further verification. public static final String CT_V4NEW_HEX = // CHECKSTYLE:OFF IndentationCheck // struct nlmsghdr "14000000" + // length = 20 "0001" + // type = NFNL_SUBSYS_CTNETLINK (1) << 8 | IPCTNL_MSG_CT_NEW (0) "0006" + // flags = NLM_F_CREATE | NLM_F_EXCL "00000000" + // seqno = 0 "00000000" + // pid = 0 // struct nfgenmsg "02" + // nfgen_family = AF_INET "00" + // version = NFNETLINK_V0 "0000"; // res_id // CHECKSTYLE:ON IndentationCheck public static final byte[] CT_V4NEW_BYTES = HexEncoding.decode(CT_V4NEW_HEX.replaceAll(" ", "").toCharArray(), false); @Test public void testConntrackEvent_New() throws Exception { mConntrackMonitor.sendMessage(CT_V4NEW_BYTES); verify(mConsumer, timeout(TIMEOUT_MS)).accept(any() /* TODO: check the content */); } }
tests/unit/src/android/net/netlink/NetlinkConstantsTest.java 0 → 100644 +131 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.net.netlink; import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_DELETE; import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_GET; import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_GET_CTRZERO; import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_GET_DYING; import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_GET_STATS; import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_GET_STATS_CPU; import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_GET_UNCONFIRMED; import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_NEW; import static android.net.netlink.NetlinkConstants.NFNL_SUBSYS_CTNETLINK; import static android.net.netlink.NetlinkConstants.NLMSG_DONE; import static android.net.netlink.NetlinkConstants.NLMSG_ERROR; import static android.net.netlink.NetlinkConstants.NLMSG_NOOP; import static android.net.netlink.NetlinkConstants.NLMSG_OVERRUN; import static android.net.netlink.NetlinkConstants.RTM_DELADDR; import static android.net.netlink.NetlinkConstants.RTM_DELLINK; import static android.net.netlink.NetlinkConstants.RTM_DELNEIGH; import static android.net.netlink.NetlinkConstants.RTM_DELROUTE; import static android.net.netlink.NetlinkConstants.RTM_DELRULE; import static android.net.netlink.NetlinkConstants.RTM_GETADDR; import static android.net.netlink.NetlinkConstants.RTM_GETLINK; import static android.net.netlink.NetlinkConstants.RTM_GETNEIGH; import static android.net.netlink.NetlinkConstants.RTM_GETROUTE; import static android.net.netlink.NetlinkConstants.RTM_GETRULE; import static android.net.netlink.NetlinkConstants.RTM_NEWADDR; import static android.net.netlink.NetlinkConstants.RTM_NEWLINK; import static android.net.netlink.NetlinkConstants.RTM_NEWNDUSEROPT; import static android.net.netlink.NetlinkConstants.RTM_NEWNEIGH; import static android.net.netlink.NetlinkConstants.RTM_NEWROUTE; import static android.net.netlink.NetlinkConstants.RTM_NEWRULE; import static android.net.netlink.NetlinkConstants.RTM_SETLINK; import static android.net.netlink.NetlinkConstants.SOCK_DIAG_BY_FAMILY; import static android.net.netlink.NetlinkConstants.stringForNlMsgType; import static android.system.OsConstants.NETLINK_INET_DIAG; import static android.system.OsConstants.NETLINK_NETFILTER; import static android.system.OsConstants.NETLINK_ROUTE; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) @SmallTest public class NetlinkConstantsTest { private static final short UNKNOWN_FAMILY = 1234; private short makeCtType(short msgType) { return (short) (NFNL_SUBSYS_CTNETLINK << 8 | (byte) msgType); } @Test public void testStringForNlMsgType() { assertEquals("RTM_NEWLINK", stringForNlMsgType(RTM_NEWLINK, NETLINK_ROUTE)); assertEquals("RTM_DELLINK", stringForNlMsgType(RTM_DELLINK, NETLINK_ROUTE)); assertEquals("RTM_GETLINK", stringForNlMsgType(RTM_GETLINK, NETLINK_ROUTE)); assertEquals("RTM_SETLINK", stringForNlMsgType(RTM_SETLINK, NETLINK_ROUTE)); assertEquals("RTM_NEWADDR", stringForNlMsgType(RTM_NEWADDR, NETLINK_ROUTE)); assertEquals("RTM_DELADDR", stringForNlMsgType(RTM_DELADDR, NETLINK_ROUTE)); assertEquals("RTM_GETADDR", stringForNlMsgType(RTM_GETADDR, NETLINK_ROUTE)); assertEquals("RTM_NEWROUTE", stringForNlMsgType(RTM_NEWROUTE, NETLINK_ROUTE)); assertEquals("RTM_DELROUTE", stringForNlMsgType(RTM_DELROUTE, NETLINK_ROUTE)); assertEquals("RTM_GETROUTE", stringForNlMsgType(RTM_GETROUTE, NETLINK_ROUTE)); assertEquals("RTM_NEWNEIGH", stringForNlMsgType(RTM_NEWNEIGH, NETLINK_ROUTE)); assertEquals("RTM_DELNEIGH", stringForNlMsgType(RTM_DELNEIGH, NETLINK_ROUTE)); assertEquals("RTM_GETNEIGH", stringForNlMsgType(RTM_GETNEIGH, NETLINK_ROUTE)); assertEquals("RTM_NEWRULE", stringForNlMsgType(RTM_NEWRULE, NETLINK_ROUTE)); assertEquals("RTM_DELRULE", stringForNlMsgType(RTM_DELRULE, NETLINK_ROUTE)); assertEquals("RTM_GETRULE", stringForNlMsgType(RTM_GETRULE, NETLINK_ROUTE)); assertEquals("RTM_NEWNDUSEROPT", stringForNlMsgType(RTM_NEWNDUSEROPT, NETLINK_ROUTE)); assertEquals("SOCK_DIAG_BY_FAMILY", stringForNlMsgType(SOCK_DIAG_BY_FAMILY, NETLINK_INET_DIAG)); assertEquals("IPCTNL_MSG_CT_NEW", stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_NEW), NETLINK_NETFILTER)); assertEquals("IPCTNL_MSG_CT_GET", stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_GET), NETLINK_NETFILTER)); assertEquals("IPCTNL_MSG_CT_DELETE", stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_DELETE), NETLINK_NETFILTER)); assertEquals("IPCTNL_MSG_CT_GET_CTRZERO", stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_GET_CTRZERO), NETLINK_NETFILTER)); assertEquals("IPCTNL_MSG_CT_GET_STATS_CPU", stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_GET_STATS_CPU), NETLINK_NETFILTER)); assertEquals("IPCTNL_MSG_CT_GET_STATS", stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_GET_STATS), NETLINK_NETFILTER)); assertEquals("IPCTNL_MSG_CT_GET_DYING", stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_GET_DYING), NETLINK_NETFILTER)); assertEquals("IPCTNL_MSG_CT_GET_UNCONFIRMED", stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_GET_UNCONFIRMED), NETLINK_NETFILTER)); } @Test public void testStringForNlMsgType_ControlMessage() { for (int family : new int[]{NETLINK_ROUTE, NETLINK_INET_DIAG, NETLINK_NETFILTER}) { assertEquals("NLMSG_NOOP", stringForNlMsgType(NLMSG_NOOP, family)); assertEquals("NLMSG_ERROR", stringForNlMsgType(NLMSG_ERROR, family)); assertEquals("NLMSG_DONE", stringForNlMsgType(NLMSG_DONE, family)); assertEquals("NLMSG_OVERRUN", stringForNlMsgType(NLMSG_OVERRUN, family)); } } @Test public void testStringForNlMsgType_UnknownFamily() { assertTrue(stringForNlMsgType(RTM_NEWLINK, UNKNOWN_FAMILY).startsWith("unknown")); assertTrue(stringForNlMsgType(SOCK_DIAG_BY_FAMILY, UNKNOWN_FAMILY).startsWith("unknown")); assertTrue(stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_NEW), UNKNOWN_FAMILY) .startsWith("unknown")); } }
tests/unit/src/android/net/netlink/StructNlMsgHdrTest.java 0 → 100644 +102 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.net.netlink; import static org.junit.Assert.fail; import android.system.OsConstants; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) @SmallTest public class StructNlMsgHdrTest { public static final short TEST_NLMSG_LEN = 16; public static final short TEST_NLMSG_FLAGS = StructNlMsgHdr.NLM_F_REQUEST | StructNlMsgHdr.NLM_F_MULTI | StructNlMsgHdr.NLM_F_ACK | StructNlMsgHdr.NLM_F_ECHO; public static final short TEST_NLMSG_SEQ = 1234; public static final short TEST_NLMSG_PID = 5678; // Checking the header string nlmsg_{len, ..} of the number can make sure that the checking // number comes from the expected element. // TODO: Verify more flags once StructNlMsgHdr can distinguish the flags which have the same // value. For example, NLM_F_MATCH (0x200) and NLM_F_EXCL (0x200) can't be distinguished. // See StructNlMsgHdrTest#stringForNlMsgFlags. public static final String TEST_NLMSG_LEN_STR = "nlmsg_len{16}"; public static final String TEST_NLMSG_FLAGS_STR = "NLM_F_REQUEST|NLM_F_MULTI|NLM_F_ACK|NLM_F_ECHO"; public static final String TEST_NLMSG_SEQ_STR = "nlmsg_seq{1234}"; public static final String TEST_NLMSG_PID_STR = "nlmsg_pid{5678}"; private StructNlMsgHdr makeStructNlMsgHdr(short type) { final StructNlMsgHdr struct = new StructNlMsgHdr(); struct.nlmsg_len = TEST_NLMSG_LEN; struct.nlmsg_type = type; struct.nlmsg_flags = TEST_NLMSG_FLAGS; struct.nlmsg_seq = TEST_NLMSG_SEQ; struct.nlmsg_pid = TEST_NLMSG_PID; return struct; } private static void assertContains(String actualValue, String expectedSubstring) { if (actualValue.contains(expectedSubstring)) return; fail("\"" + actualValue + "\" does not contain \"" + expectedSubstring + "\""); } @Test public void testToString() { StructNlMsgHdr struct = makeStructNlMsgHdr(NetlinkConstants.RTM_NEWADDR); String s = struct.toString(); assertContains(s, TEST_NLMSG_LEN_STR); assertContains(s, TEST_NLMSG_FLAGS_STR); assertContains(s, TEST_NLMSG_SEQ_STR); assertContains(s, TEST_NLMSG_PID_STR); assertContains(s, "nlmsg_type{20()}"); struct = makeStructNlMsgHdr(NetlinkConstants.SOCK_DIAG_BY_FAMILY); s = struct.toString(); assertContains(s, TEST_NLMSG_LEN_STR); assertContains(s, TEST_NLMSG_FLAGS_STR); assertContains(s, TEST_NLMSG_SEQ_STR); assertContains(s, TEST_NLMSG_PID_STR); assertContains(s, "nlmsg_type{20()}"); } @Test public void testToStringWithNetlinkFamily() { StructNlMsgHdr struct = makeStructNlMsgHdr(NetlinkConstants.RTM_NEWADDR); String s = struct.toString(OsConstants.NETLINK_ROUTE); assertContains(s, TEST_NLMSG_LEN_STR); assertContains(s, TEST_NLMSG_FLAGS_STR); assertContains(s, TEST_NLMSG_SEQ_STR); assertContains(s, TEST_NLMSG_PID_STR); assertContains(s, "nlmsg_type{20(RTM_NEWADDR)}"); struct = makeStructNlMsgHdr(NetlinkConstants.SOCK_DIAG_BY_FAMILY); s = struct.toString(OsConstants.NETLINK_INET_DIAG); assertContains(s, TEST_NLMSG_LEN_STR); assertContains(s, TEST_NLMSG_FLAGS_STR); assertContains(s, TEST_NLMSG_SEQ_STR); assertContains(s, TEST_NLMSG_PID_STR); assertContains(s, "nlmsg_type{20(SOCK_DIAG_BY_FAMILY)}"); } }