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

Commit b7284f60 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "tethering: offload: Netlink Req" into rvc-dev

parents 82ff3f14 8c2e6b8a
Loading
Loading
Loading
Loading
+33 −0
Original line number Original line Diff line number Diff line
@@ -16,8 +16,11 @@


package com.android.networkstack.tethering;
package com.android.networkstack.tethering;


import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP;
import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
import static android.net.util.TetheringUtils.uint16;
import static android.net.util.TetheringUtils.uint16;


import android.annotation.NonNull;
import android.hardware.tetheroffload.config.V1_0.IOffloadConfig;
import android.hardware.tetheroffload.config.V1_0.IOffloadConfig;
import android.hardware.tetheroffload.control.V1_0.IOffloadControl;
import android.hardware.tetheroffload.control.V1_0.IOffloadControl;
import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback;
import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback;
@@ -25,6 +28,7 @@ import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate;
import android.hardware.tetheroffload.control.V1_0.NetworkProtocol;
import android.hardware.tetheroffload.control.V1_0.NetworkProtocol;
import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent;
import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent;
import android.net.netlink.NetlinkSocket;
import android.net.netlink.NetlinkSocket;
import android.net.netlink.StructNlMsgHdr;
import android.net.util.SharedLog;
import android.net.util.SharedLog;
import android.net.util.SocketUtils;
import android.net.util.SocketUtils;
import android.os.Handler;
import android.os.Handler;
@@ -37,9 +41,11 @@ import android.system.OsConstants;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;


import java.io.FileDescriptor;
import java.io.FileDescriptor;
import java.io.InterruptedIOException;
import java.io.IOException;
import java.io.IOException;
import java.net.SocketAddress;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.NoSuchElementException;
import java.util.NoSuchElementException;


@@ -63,6 +69,11 @@ public class OffloadHardwareInterface {
    private static final int NF_NETLINK_CONNTRACK_NEW = 1;
    private static final int NF_NETLINK_CONNTRACK_NEW = 1;
    private static final int NF_NETLINK_CONNTRACK_UPDATE = 2;
    private static final int NF_NETLINK_CONNTRACK_UPDATE = 2;
    private static final int NF_NETLINK_CONNTRACK_DESTROY = 4;
    private static final int NF_NETLINK_CONNTRACK_DESTROY = 4;
    // Reference libnetfilter_conntrack/linux_nfnetlink_conntrack.h
    public static final short NFNL_SUBSYS_CTNETLINK = 1;
    public static final short IPCTNL_MSG_CT_GET = 1;

    private final long NETLINK_MESSAGE_TIMEOUT_MS = 500;


    private final Handler mHandler;
    private final Handler mHandler;
    private final SharedLog mLog;
    private final SharedLog mLog;
@@ -226,6 +237,9 @@ public class OffloadHardwareInterface {
                NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY);
                NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY);
        if (h1 == null) return false;
        if (h1 == null) return false;


        sendNetlinkMessage(h1, (short) ((NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_GET),
                           (short) (NLM_F_REQUEST | NLM_F_DUMP));

        final NativeHandle h2 = mDeps.createConntrackSocket(
        final NativeHandle h2 = mDeps.createConntrackSocket(
                NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY);
                NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY);
        if (h2 == null) {
        if (h2 == null) {
@@ -252,6 +266,25 @@ public class OffloadHardwareInterface {
        return results.mSuccess;
        return results.mSuccess;
    }
    }


    @VisibleForTesting
    public void sendNetlinkMessage(@NonNull NativeHandle handle, short type, short flags) {
        final int length = StructNlMsgHdr.STRUCT_SIZE;
        final byte[] msg = new byte[length];
        final StructNlMsgHdr nlh = new StructNlMsgHdr();
        final ByteBuffer byteBuffer = ByteBuffer.wrap(msg);
        nlh.nlmsg_len = length;
        nlh.nlmsg_type = type;
        nlh.nlmsg_flags = flags;
        nlh.nlmsg_seq = 1;
        nlh.pack(byteBuffer);
        try {
            NetlinkSocket.sendMessage(handle.getFileDescriptor(), msg, 0 /* offset */, length,
                                      NETLINK_MESSAGE_TIMEOUT_MS);
        } catch (ErrnoException | InterruptedIOException e) {
            mLog.e("Unable to send netfilter message, error: " + e);
        }
    }

    private void closeFdInNativeHandle(final NativeHandle h) {
    private void closeFdInNativeHandle(final NativeHandle h) {
        try {
        try {
            h.close();
            h.close();
+39 −0
Original line number Original line Diff line number Diff line
@@ -17,13 +17,17 @@
package com.android.networkstack.tethering;
package com.android.networkstack.tethering;


import static android.net.util.TetheringUtils.uint16;
import static android.net.util.TetheringUtils.uint16;
import static android.system.OsConstants.SOCK_STREAM;
import static android.system.OsConstants.AF_UNIX;


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;


import android.hardware.tetheroffload.config.V1_0.IOffloadConfig;
import android.hardware.tetheroffload.config.V1_0.IOffloadConfig;
import android.hardware.tetheroffload.control.V1_0.IOffloadControl;
import android.hardware.tetheroffload.control.V1_0.IOffloadControl;
@@ -31,11 +35,14 @@ import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback;
import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate;
import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate;
import android.hardware.tetheroffload.control.V1_0.NetworkProtocol;
import android.hardware.tetheroffload.control.V1_0.NetworkProtocol;
import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent;
import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent;
import android.net.netlink.StructNlMsgHdr;
import android.net.util.SharedLog;
import android.net.util.SharedLog;
import android.os.Handler;
import android.os.Handler;
import android.os.NativeHandle;
import android.os.NativeHandle;
import android.os.test.TestLooper;
import android.os.test.TestLooper;
import android.system.ErrnoException;
import android.system.OsConstants;
import android.system.OsConstants;
import android.system.Os;


import androidx.test.filters.SmallTest;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.runner.AndroidJUnit4;
@@ -47,6 +54,9 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoAnnotations;


import java.io.FileDescriptor;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.ArrayList;


@RunWith(AndroidJUnit4.class)
@RunWith(AndroidJUnit4.class)
@@ -64,6 +74,10 @@ public final class OffloadHardwareInterfaceTest {
    @Mock private IOffloadControl mIOffloadControl;
    @Mock private IOffloadControl mIOffloadControl;
    @Mock private NativeHandle mNativeHandle;
    @Mock private NativeHandle mNativeHandle;


    // Random values to test Netlink message.
    private static final short TEST_TYPE = 184;
    private static final short TEST_FLAGS = 263;

    class MyDependencies extends OffloadHardwareInterface.Dependencies {
    class MyDependencies extends OffloadHardwareInterface.Dependencies {
        MyDependencies(SharedLog log) {
        MyDependencies(SharedLog log) {
            super(log);
            super(log);
@@ -203,6 +217,31 @@ public final class OffloadHardwareInterfaceTest {
                eq(uint16(udpParams.dst.port)));
                eq(uint16(udpParams.dst.port)));
    }
    }


    @Test
    public void testNetlinkMessage() throws Exception {
        FileDescriptor writeSocket = new FileDescriptor();
        FileDescriptor readSocket = new FileDescriptor();
        try {
            Os.socketpair(AF_UNIX, SOCK_STREAM, 0, writeSocket, readSocket);
        } catch (ErrnoException e) {
            fail();
            return;
        }
        when(mNativeHandle.getFileDescriptor()).thenReturn(writeSocket);

        mOffloadHw.sendNetlinkMessage(mNativeHandle, TEST_TYPE, TEST_FLAGS);

        ByteBuffer buffer = ByteBuffer.allocate(StructNlMsgHdr.STRUCT_SIZE);
        int read = Os.read(readSocket, buffer);

        buffer.flip();
        assertEquals(StructNlMsgHdr.STRUCT_SIZE, buffer.getInt());
        assertEquals(TEST_TYPE, buffer.getShort());
        assertEquals(TEST_FLAGS, buffer.getShort());
        assertEquals(1 /* seq */, buffer.getInt());
        assertEquals(0 /* pid */, buffer.getInt());
    }

    private NatTimeoutUpdate buildNatTimeoutUpdate(final int proto) {
    private NatTimeoutUpdate buildNatTimeoutUpdate(final int proto) {
        final NatTimeoutUpdate params = new NatTimeoutUpdate();
        final NatTimeoutUpdate params = new NatTimeoutUpdate();
        params.proto = proto;
        params.proto = proto;