Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d41dfd2f authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 6976352 from 8134bae0 to sc-release

Change-Id: I053aafc1f94e889296a707271ed335852e039e96
parents 1dd328f2 8134bae0
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -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);
        }

+5 −2
Original line number Diff line number Diff line
@@ -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) {
@@ -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
+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 */);
    }
}
+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"));
    }
}
+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)}");
    }
}