Loading common/moduleutils/Android.bp +12 −0 Original line number Original line Diff line number Diff line Loading @@ -62,3 +62,15 @@ filegroup { ], ], visibility: ["//frameworks/base/packages/Tethering"], visibility: ["//frameworks/base/packages/Tethering"], } } // Utility sources used by test libraries. // This is its own group to limit indiscriminate dependency of test code on production code. // TODO: move these classes and NetworkStack/tests/lib to frameworks/libs/net, and remove this. filegroup { name: "net-module-utils-srcs-for-tests", visibility: ["//packages/modules/NetworkStack/tests/lib"], srcs: [ "src/android/net/util/FdEventsReader.java", "src/android/net/util/PacketReader.java", ], } src/android/net/dhcp/DhcpPacket.java +22 −23 Original line number Original line Diff line number Diff line Loading @@ -162,49 +162,49 @@ public abstract class DhcpPacket { /** /** * DHCP Optional Type: DHCP Subnet Mask * DHCP Optional Type: DHCP Subnet Mask */ */ protected static final byte DHCP_SUBNET_MASK = 1; public static final byte DHCP_SUBNET_MASK = 1; protected Inet4Address mSubnetMask; protected Inet4Address mSubnetMask; /** /** * DHCP Optional Type: DHCP Router * DHCP Optional Type: DHCP Router */ */ protected static final byte DHCP_ROUTER = 3; public static final byte DHCP_ROUTER = 3; protected List <Inet4Address> mGateways; protected List <Inet4Address> mGateways; /** /** * DHCP Optional Type: DHCP DNS Server * DHCP Optional Type: DHCP DNS Server */ */ protected static final byte DHCP_DNS_SERVER = 6; public static final byte DHCP_DNS_SERVER = 6; protected List<Inet4Address> mDnsServers; protected List<Inet4Address> mDnsServers; /** /** * DHCP Optional Type: DHCP Host Name * DHCP Optional Type: DHCP Host Name */ */ protected static final byte DHCP_HOST_NAME = 12; public static final byte DHCP_HOST_NAME = 12; protected String mHostName; protected String mHostName; /** /** * DHCP Optional Type: DHCP DOMAIN NAME * DHCP Optional Type: DHCP DOMAIN NAME */ */ protected static final byte DHCP_DOMAIN_NAME = 15; public static final byte DHCP_DOMAIN_NAME = 15; protected String mDomainName; protected String mDomainName; /** /** * DHCP Optional Type: DHCP Interface MTU * DHCP Optional Type: DHCP Interface MTU */ */ protected static final byte DHCP_MTU = 26; public static final byte DHCP_MTU = 26; protected Short mMtu; protected Short mMtu; /** /** * DHCP Optional Type: DHCP BROADCAST ADDRESS * DHCP Optional Type: DHCP BROADCAST ADDRESS */ */ protected static final byte DHCP_BROADCAST_ADDRESS = 28; public static final byte DHCP_BROADCAST_ADDRESS = 28; protected Inet4Address mBroadcastAddress; protected Inet4Address mBroadcastAddress; /** /** * DHCP Optional Type: Vendor specific information * DHCP Optional Type: Vendor specific information */ */ protected static final byte DHCP_VENDOR_INFO = 43; public static final byte DHCP_VENDOR_INFO = 43; protected String mVendorInfo; protected String mVendorInfo; /** /** Loading @@ -215,7 +215,7 @@ public abstract class DhcpPacket { /** /** * DHCP Optional Type: Option overload option * DHCP Optional Type: Option overload option */ */ protected static final byte DHCP_OPTION_OVERLOAD = 52; public static final byte DHCP_OPTION_OVERLOAD = 52; /** /** * Possible values of the option overload option. * Possible values of the option overload option. Loading @@ -227,14 +227,14 @@ public abstract class DhcpPacket { /** /** * DHCP Optional Type: DHCP Requested IP Address * DHCP Optional Type: DHCP Requested IP Address */ */ protected static final byte DHCP_REQUESTED_IP = 50; public static final byte DHCP_REQUESTED_IP = 50; @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) public Inet4Address mRequestedIp; public Inet4Address mRequestedIp; /** /** * DHCP Optional Type: DHCP Lease Time * DHCP Optional Type: DHCP Lease Time */ */ protected static final byte DHCP_LEASE_TIME = 51; public static final byte DHCP_LEASE_TIME = 51; protected Integer mLeaseTime; protected Integer mLeaseTime; /** /** Loading @@ -254,72 +254,71 @@ public abstract class DhcpPacket { /** /** * DHCP Optional Type: DHCP Server Identifier * DHCP Optional Type: DHCP Server Identifier */ */ protected static final byte DHCP_SERVER_IDENTIFIER = 54; public static final byte DHCP_SERVER_IDENTIFIER = 54; @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) public Inet4Address mServerIdentifier; public Inet4Address mServerIdentifier; /** /** * DHCP Optional Type: DHCP Parameter List * DHCP Optional Type: DHCP Parameter List */ */ protected static final byte DHCP_PARAMETER_LIST = 55; public static final byte DHCP_PARAMETER_LIST = 55; protected byte[] mRequestedParams; protected byte[] mRequestedParams; /** /** * DHCP Optional Type: DHCP MESSAGE * DHCP Optional Type: DHCP MESSAGE */ */ protected static final byte DHCP_MESSAGE = 56; public static final byte DHCP_MESSAGE = 56; protected String mMessage; protected String mMessage; /** /** * DHCP Optional Type: Maximum DHCP Message Size * DHCP Optional Type: Maximum DHCP Message Size */ */ protected static final byte DHCP_MAX_MESSAGE_SIZE = 57; public static final byte DHCP_MAX_MESSAGE_SIZE = 57; protected Short mMaxMessageSize; protected Short mMaxMessageSize; /** /** * DHCP Optional Type: DHCP Renewal Time Value * DHCP Optional Type: DHCP Renewal Time Value */ */ protected static final byte DHCP_RENEWAL_TIME = 58; public static final byte DHCP_RENEWAL_TIME = 58; protected Integer mT1; protected Integer mT1; /** /** * DHCP Optional Type: Rebinding Time Value * DHCP Optional Type: Rebinding Time Value */ */ protected static final byte DHCP_REBINDING_TIME = 59; public static final byte DHCP_REBINDING_TIME = 59; protected Integer mT2; protected Integer mT2; /** /** * DHCP Optional Type: Vendor Class Identifier * DHCP Optional Type: Vendor Class Identifier */ */ protected static final byte DHCP_VENDOR_CLASS_ID = 60; public static final byte DHCP_VENDOR_CLASS_ID = 60; protected String mVendorId; protected String mVendorId; /** /** * DHCP Optional Type: DHCP Client Identifier * DHCP Optional Type: DHCP Client Identifier */ */ protected static final byte DHCP_CLIENT_IDENTIFIER = 61; public static final byte DHCP_CLIENT_IDENTIFIER = 61; protected byte[] mClientId; protected byte[] mClientId; /** /** * DHCP zero-length Optional Type: Rapid Commit. Per RFC4039, both DHCPDISCOVER and DHCPACK * DHCP zero-length Optional Type: Rapid Commit. Per RFC4039, both DHCPDISCOVER and DHCPACK * packet may include this option. * packet may include this option. */ */ protected static final byte DHCP_RAPID_COMMIT = 80; public static final byte DHCP_RAPID_COMMIT = 80; protected boolean mRapidCommit; protected boolean mRapidCommit; @VisibleForTesting public static final byte DHCP_CAPTIVE_PORTAL = (byte) 114; public static final byte DHCP_CAPTIVE_PORTAL = (byte) 114; protected String mCaptivePortalUrl; protected String mCaptivePortalUrl; /** /** * DHCP zero-length option code: pad * DHCP zero-length option code: pad */ */ protected static final byte DHCP_OPTION_PAD = 0x00; public static final byte DHCP_OPTION_PAD = 0x00; /** /** * DHCP zero-length option code: end of options * DHCP zero-length option code: end of options */ */ protected static final byte DHCP_OPTION_END = (byte) 0xff; public static final byte DHCP_OPTION_END = (byte) 0xff; /** /** * The transaction identifier used in this particular DHCP negotiation * The transaction identifier used in this particular DHCP negotiation Loading tests/integration/src/android/net/ip/IpClientIntegrationTest.java +20 −72 Original line number Original line Diff line number Diff line Loading @@ -109,19 +109,16 @@ import android.net.shared.ProvisioningConfiguration.ScanResultInfo; import android.net.util.InterfaceParams; import android.net.util.InterfaceParams; import android.net.util.IpUtils; import android.net.util.IpUtils; import android.net.util.NetworkStackUtils; import android.net.util.NetworkStackUtils; import android.net.util.PacketReader; import android.os.Build; import android.os.Build; import android.os.Handler; import android.os.Handler; import android.os.HandlerThread; import android.os.HandlerThread; import android.os.IBinder; import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.PowerManager; import android.os.PowerManager; import android.os.RemoteException; import android.os.RemoteException; import android.os.SystemProperties; import android.os.SystemProperties; import android.system.ErrnoException; import android.system.ErrnoException; import android.system.Os; import android.system.Os; import androidx.annotation.Nullable; import androidx.test.InstrumentationRegistry; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import androidx.test.runner.AndroidJUnit4; Loading @@ -134,6 +131,7 @@ import com.android.server.NetworkObserverRegistry; import com.android.server.NetworkStackService.NetworkStackServiceManager; import com.android.server.NetworkStackService.NetworkStackServiceManager; import com.android.server.connectivity.ipmemorystore.IpMemoryStoreService; import com.android.server.connectivity.ipmemorystore.IpMemoryStoreService; import com.android.testutils.HandlerUtilsKt; import com.android.testutils.HandlerUtilsKt; import com.android.testutils.TapPacketReader; import org.junit.After; import org.junit.After; import org.junit.Before; import org.junit.Before; Loading @@ -145,7 +143,6 @@ import org.mockito.MockitoAnnotations; import org.mockito.Spy; import org.mockito.Spy; import java.io.FileDescriptor; import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.IOException; import java.io.IOException; import java.net.Inet4Address; import java.net.Inet4Address; import java.net.InetAddress; import java.net.InetAddress; Loading @@ -159,8 +156,6 @@ import java.util.HashMap; import java.util.List; import java.util.List; import java.util.Objects; import java.util.Objects; import java.util.Random; import java.util.Random; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; /** /** * Tests for IpClient. * Tests for IpClient. Loading Loading @@ -192,6 +187,7 @@ public class IpClientIntegrationTest { private HandlerThread mPacketReaderThread; private HandlerThread mPacketReaderThread; private Handler mHandler; private Handler mHandler; private TapPacketReader mPacketReader; private TapPacketReader mPacketReader; private FileDescriptor mTapFd; private IpClient mIpc; private IpClient mIpc; private Dependencies mDependencies; private Dependencies mDependencies; private byte[] mClientMac; private byte[] mClientMac; Loading Loading @@ -238,46 +234,6 @@ public class IpClientIntegrationTest { }; }; private static final byte TEST_VENDOR_SPECIFIC_TYPE = 0x06; private static final byte TEST_VENDOR_SPECIFIC_TYPE = 0x06; private static class TapPacketReader extends PacketReader { private final ParcelFileDescriptor mTapFd; private final LinkedBlockingQueue<byte[]> mReceivedPackets = new LinkedBlockingQueue<byte[]>(); TapPacketReader(Handler h, ParcelFileDescriptor tapFd) { super(h, DATA_BUFFER_LEN); mTapFd = tapFd; } @Override protected FileDescriptor createFd() { return mTapFd.getFileDescriptor(); } @Override protected void handlePacket(byte[] recvbuf, int length) { final byte[] newPacket = Arrays.copyOf(recvbuf, length); try { mReceivedPackets.put(newPacket); } catch (InterruptedException e) { fail("fail to put the new packet in the queue"); } } /** * Get the next packet that was received on the interface. * */ @Nullable public byte[] popPacket(long timeoutMs) { try { return mReceivedPackets.poll(timeoutMs, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { // Fall through } return null; } } private class Dependencies extends IpClient.Dependencies { private class Dependencies extends IpClient.Dependencies { private boolean mIsDhcpLeaseCacheEnabled; private boolean mIsDhcpLeaseCacheEnabled; private boolean mIsDhcpRapidCommitEnabled; private boolean mIsDhcpRapidCommitEnabled; Loading Loading @@ -411,6 +367,7 @@ public class IpClientIntegrationTest { public void tearDown() throws Exception { public void tearDown() throws Exception { if (mPacketReader != null) { if (mPacketReader != null) { mHandler.post(() -> mPacketReader.stop()); // Also closes the socket mHandler.post(() -> mPacketReader.stop()); // Also closes the socket mTapFd = null; } } if (mPacketReaderThread != null) { if (mPacketReaderThread != null) { mPacketReaderThread.quitSafely(); mPacketReaderThread.quitSafely(); Loading Loading @@ -440,8 +397,8 @@ public class IpClientIntegrationTest { mPacketReaderThread.start(); mPacketReaderThread.start(); mHandler = mPacketReaderThread.getThreadHandler(); mHandler = mPacketReaderThread.getThreadHandler(); final ParcelFileDescriptor tapFd = iface.getFileDescriptor(); mTapFd = iface.getFileDescriptor().getFileDescriptor(); mPacketReader = new TapPacketReader(mHandler, tapFd); mPacketReader = new TapPacketReader(mHandler, mTapFd, DATA_BUFFER_LEN); mHandler.post(() -> mPacketReader.start()); mHandler.post(() -> mPacketReader.start()); } } Loading Loading @@ -532,21 +489,12 @@ public class IpClientIntegrationTest { false /* broadcast */, "duplicated request IP address"); false /* broadcast */, "duplicated request IP address"); } } private void sendResponse(final ByteBuffer packet) throws IOException { try (FileOutputStream out = new FileOutputStream(mPacketReader.createFd())) { byte[] packetBytes = new byte[packet.limit()]; packet.get(packetBytes); packet.flip(); // So we can reuse it in the future. out.write(packetBytes); } } private void sendArpReply(final byte[] clientMac) throws IOException { private void sendArpReply(final byte[] clientMac) throws IOException { final ByteBuffer packet = ArpPacket.buildArpPacket(clientMac /* dst */, final ByteBuffer packet = ArpPacket.buildArpPacket(clientMac /* dst */, SERVER_MAC /* src */, INADDR_ANY.getAddress() /* target IP */, SERVER_MAC /* src */, INADDR_ANY.getAddress() /* target IP */, clientMac /* target HW address */, CLIENT_ADDR.getAddress() /* sender IP */, clientMac /* target HW address */, CLIENT_ADDR.getAddress() /* sender IP */, (short) ARP_REPLY); (short) ARP_REPLY); sendResponse(packet); mPacketReader.sendResponse(packet); } } private void sendArpProbe() throws IOException { private void sendArpProbe() throws IOException { Loading @@ -554,7 +502,7 @@ public class IpClientIntegrationTest { SERVER_MAC /* src */, CLIENT_ADDR.getAddress() /* target IP */, SERVER_MAC /* src */, CLIENT_ADDR.getAddress() /* target IP */, new byte[ETHER_ADDR_LEN] /* target HW address */, new byte[ETHER_ADDR_LEN] /* target HW address */, INADDR_ANY.getAddress() /* sender IP */, (short) ARP_REQUEST); INADDR_ANY.getAddress() /* sender IP */, (short) ARP_REQUEST); sendResponse(packet); mPacketReader.sendResponse(packet); } } private void startIpClientProvisioning(final boolean isDhcpLeaseCacheEnabled, private void startIpClientProvisioning(final boolean isDhcpLeaseCacheEnabled, Loading Loading @@ -667,18 +615,18 @@ public class IpClientIntegrationTest { packetList.add(packet); packetList.add(packet); if (packet instanceof DhcpDiscoverPacket) { if (packet instanceof DhcpDiscoverPacket) { if (shouldReplyRapidCommitAck) { if (shouldReplyRapidCommitAck) { sendResponse(buildDhcpAckPacket(packet, leaseTimeSec, (short) mtu, mPacketReader.sendResponse(buildDhcpAckPacket(packet, leaseTimeSec, (short) mtu, true /* rapidCommit */, captivePortalApiUrl)); true /* rapidCommit */, captivePortalApiUrl)); } else { } else { sendResponse(buildDhcpOfferPacket(packet, leaseTimeSec, (short) mtu, mPacketReader.sendResponse(buildDhcpOfferPacket(packet, leaseTimeSec, captivePortalApiUrl)); (short) mtu, captivePortalApiUrl)); } } } else if (packet instanceof DhcpRequestPacket) { } else if (packet instanceof DhcpRequestPacket) { final ByteBuffer byteBuffer = isSuccessLease final ByteBuffer byteBuffer = isSuccessLease ? buildDhcpAckPacket(packet, leaseTimeSec, (short) mtu, ? buildDhcpAckPacket(packet, leaseTimeSec, (short) mtu, false /* rapidCommit */, captivePortalApiUrl) false /* rapidCommit */, captivePortalApiUrl) : buildDhcpNakPacket(packet); : buildDhcpNakPacket(packet); sendResponse(byteBuffer); mPacketReader.sendResponse(byteBuffer); } else { } else { fail("invalid DHCP packet"); fail("invalid DHCP packet"); } } Loading Loading @@ -777,7 +725,7 @@ public class IpClientIntegrationTest { assertEquals(NetworkInterface.getByName(mIfaceName).getMTU(), mtu); assertEquals(NetworkInterface.getByName(mIfaceName).getMTU(), mtu); } } if (shouldRemoveTapInterface) removeTapInterface(mPacketReader.createFd()); if (shouldRemoveTapInterface) removeTapInterface(mTapFd); try { try { mIpc.shutdown(); mIpc.shutdown(); awaitIpClientShutdown(); awaitIpClientShutdown(); Loading Loading @@ -845,12 +793,12 @@ public class IpClientIntegrationTest { final short mtu = (short) TEST_DEFAULT_MTU; final short mtu = (short) TEST_DEFAULT_MTU; if (!shouldReplyRapidCommitAck) { if (!shouldReplyRapidCommitAck) { sendResponse(buildDhcpOfferPacket(packet, TEST_LEASE_DURATION_S, mtu, mPacketReader.sendResponse(buildDhcpOfferPacket(packet, TEST_LEASE_DURATION_S, mtu, null /* captivePortalUrl */)); null /* captivePortalUrl */)); packet = getNextDhcpPacket(); packet = getNextDhcpPacket(); assertTrue(packet instanceof DhcpRequestPacket); assertTrue(packet instanceof DhcpRequestPacket); } } sendResponse(buildDhcpAckPacket(packet, TEST_LEASE_DURATION_S, mtu, mPacketReader.sendResponse(buildDhcpAckPacket(packet, TEST_LEASE_DURATION_S, mtu, shouldReplyRapidCommitAck, null /* captivePortalUrl */)); shouldReplyRapidCommitAck, null /* captivePortalUrl */)); if (!shouldAbortPreconnection) { if (!shouldAbortPreconnection) { Loading Loading @@ -1126,7 +1074,7 @@ public class IpClientIntegrationTest { @Test @Test public void testRestoreInitialInterfaceMtu_NotFoundInterfaceWhenStartingProvisioning() public void testRestoreInitialInterfaceMtu_NotFoundInterfaceWhenStartingProvisioning() throws Exception { throws Exception { removeTapInterface(mPacketReader.createFd()); removeTapInterface(mTapFd); ProvisioningConfiguration config = new ProvisioningConfiguration.Builder() ProvisioningConfiguration config = new ProvisioningConfiguration.Builder() .withoutIpReachabilityMonitor() .withoutIpReachabilityMonitor() .withoutIPv6() .withoutIPv6() Loading Loading @@ -1284,7 +1232,7 @@ public class IpClientIntegrationTest { ByteBuffer ra = buildRaPacket(pio, rdnss1, rdnss2); ByteBuffer ra = buildRaPacket(pio, rdnss1, rdnss2); waitForRouterSolicitation(); waitForRouterSolicitation(); sendResponse(ra); mPacketReader.sendResponse(ra); ArgumentCaptor<LinkProperties> captor = ArgumentCaptor.forClass(LinkProperties.class); ArgumentCaptor<LinkProperties> captor = ArgumentCaptor.forClass(LinkProperties.class); verify(mCb, timeout(TEST_TIMEOUT_MS)).onProvisioningSuccess(captor.capture()); verify(mCb, timeout(TEST_TIMEOUT_MS)).onProvisioningSuccess(captor.capture()); Loading @@ -1299,7 +1247,7 @@ public class IpClientIntegrationTest { // If the RDNSS lifetime is above the minimum, the DNS server is accepted. // If the RDNSS lifetime is above the minimum, the DNS server is accepted. rdnss1 = buildRdnssOption(68, lowlifeDnsServer); rdnss1 = buildRdnssOption(68, lowlifeDnsServer); ra = buildRaPacket(pio, rdnss1, rdnss2); ra = buildRaPacket(pio, rdnss1, rdnss2); sendResponse(ra); mPacketReader.sendResponse(ra); verify(mCb, timeout(TEST_TIMEOUT_MS)).onLinkPropertiesChange(captor.capture()); verify(mCb, timeout(TEST_TIMEOUT_MS)).onLinkPropertiesChange(captor.capture()); lp = captor.getValue(); lp = captor.getValue(); assertNotNull(lp); assertNotNull(lp); Loading @@ -1312,7 +1260,7 @@ public class IpClientIntegrationTest { rdnss1 = buildRdnssOption(0, dnsServer); rdnss1 = buildRdnssOption(0, dnsServer); rdnss2 = buildRdnssOption(0, lowlifeDnsServer); rdnss2 = buildRdnssOption(0, lowlifeDnsServer); ra = buildRaPacket(pio, rdnss1, rdnss2); ra = buildRaPacket(pio, rdnss1, rdnss2); sendResponse(ra); mPacketReader.sendResponse(ra); verify(mCb, timeout(TEST_TIMEOUT_MS)).onProvisioningFailure(captor.capture()); verify(mCb, timeout(TEST_TIMEOUT_MS)).onProvisioningFailure(captor.capture()); lp = captor.getValue(); lp = captor.getValue(); Loading Loading @@ -1546,8 +1494,8 @@ public class IpClientIntegrationTest { // Send Offer and handle Request -> Ack // Send Offer and handle Request -> Ack final String serverSentUrl = serverSendsOption ? TEST_CAPTIVE_PORTAL_URL : null; final String serverSentUrl = serverSendsOption ? TEST_CAPTIVE_PORTAL_URL : null; sendResponse(buildDhcpOfferPacket(discover, TEST_LEASE_DURATION_S, (short) TEST_DEFAULT_MTU, mPacketReader.sendResponse(buildDhcpOfferPacket(discover, TEST_LEASE_DURATION_S, serverSentUrl)); (short) TEST_DEFAULT_MTU, serverSentUrl)); final int testMtu = 1345; final int testMtu = 1345; handleDhcpPackets(true /* isSuccessLease */, TEST_LEASE_DURATION_S, handleDhcpPackets(true /* isSuccessLease */, TEST_LEASE_DURATION_S, false /* isDhcpRapidCommitEnabled */, testMtu, false /* isDhcpRapidCommitEnabled */, testMtu, Loading tests/lib/Android.bp +4 −0 Original line number Original line Diff line number Diff line Loading @@ -32,8 +32,12 @@ java_library { srcs: [ srcs: [ "src/**/*.java", "src/**/*.java", "src/**/*.kt", "src/**/*.kt", ":net-module-utils-srcs-for-tests", ], ], defaults: ["lib_mockito_extended"], defaults: ["lib_mockito_extended"], libs: [ "androidx.annotation_annotation", ], static_libs: [ static_libs: [ "net-tests-utils-multivariant", "net-tests-utils-multivariant", ], ], Loading tests/lib/src/com/android/testutils/TapPacketReader.java 0 → 100644 +76 −0 Original line number Original line 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 com.android.testutils; import android.net.util.PacketReader; import android.os.Handler; import androidx.annotation.Nullable; import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; public class TapPacketReader extends PacketReader { private final FileDescriptor mTapFd; private final LinkedBlockingQueue<byte[]> mReceivedPackets = new LinkedBlockingQueue<byte[]>(); public TapPacketReader(Handler h, FileDescriptor tapFd, int maxPacketSize) { super(h, maxPacketSize); mTapFd = tapFd; } @Override protected FileDescriptor createFd() { return mTapFd; } @Override protected void handlePacket(byte[] recvbuf, int length) { final byte[] newPacket = Arrays.copyOf(recvbuf, length); if (!mReceivedPackets.offer(newPacket)) { throw new AssertionError("More than " + Integer.MAX_VALUE + " packets outstanding!"); } } /** * Get the next packet that was received on the interface. * */ @Nullable public byte[] popPacket(long timeoutMs) { try { return mReceivedPackets.poll(timeoutMs, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { // Fall through } return null; } public void sendResponse(final ByteBuffer packet) throws IOException { try (FileOutputStream out = new FileOutputStream(mTapFd)) { byte[] packetBytes = new byte[packet.limit()]; packet.get(packetBytes); packet.flip(); // So we can reuse it in the future. out.write(packetBytes); } } } Loading
common/moduleutils/Android.bp +12 −0 Original line number Original line Diff line number Diff line Loading @@ -62,3 +62,15 @@ filegroup { ], ], visibility: ["//frameworks/base/packages/Tethering"], visibility: ["//frameworks/base/packages/Tethering"], } } // Utility sources used by test libraries. // This is its own group to limit indiscriminate dependency of test code on production code. // TODO: move these classes and NetworkStack/tests/lib to frameworks/libs/net, and remove this. filegroup { name: "net-module-utils-srcs-for-tests", visibility: ["//packages/modules/NetworkStack/tests/lib"], srcs: [ "src/android/net/util/FdEventsReader.java", "src/android/net/util/PacketReader.java", ], }
src/android/net/dhcp/DhcpPacket.java +22 −23 Original line number Original line Diff line number Diff line Loading @@ -162,49 +162,49 @@ public abstract class DhcpPacket { /** /** * DHCP Optional Type: DHCP Subnet Mask * DHCP Optional Type: DHCP Subnet Mask */ */ protected static final byte DHCP_SUBNET_MASK = 1; public static final byte DHCP_SUBNET_MASK = 1; protected Inet4Address mSubnetMask; protected Inet4Address mSubnetMask; /** /** * DHCP Optional Type: DHCP Router * DHCP Optional Type: DHCP Router */ */ protected static final byte DHCP_ROUTER = 3; public static final byte DHCP_ROUTER = 3; protected List <Inet4Address> mGateways; protected List <Inet4Address> mGateways; /** /** * DHCP Optional Type: DHCP DNS Server * DHCP Optional Type: DHCP DNS Server */ */ protected static final byte DHCP_DNS_SERVER = 6; public static final byte DHCP_DNS_SERVER = 6; protected List<Inet4Address> mDnsServers; protected List<Inet4Address> mDnsServers; /** /** * DHCP Optional Type: DHCP Host Name * DHCP Optional Type: DHCP Host Name */ */ protected static final byte DHCP_HOST_NAME = 12; public static final byte DHCP_HOST_NAME = 12; protected String mHostName; protected String mHostName; /** /** * DHCP Optional Type: DHCP DOMAIN NAME * DHCP Optional Type: DHCP DOMAIN NAME */ */ protected static final byte DHCP_DOMAIN_NAME = 15; public static final byte DHCP_DOMAIN_NAME = 15; protected String mDomainName; protected String mDomainName; /** /** * DHCP Optional Type: DHCP Interface MTU * DHCP Optional Type: DHCP Interface MTU */ */ protected static final byte DHCP_MTU = 26; public static final byte DHCP_MTU = 26; protected Short mMtu; protected Short mMtu; /** /** * DHCP Optional Type: DHCP BROADCAST ADDRESS * DHCP Optional Type: DHCP BROADCAST ADDRESS */ */ protected static final byte DHCP_BROADCAST_ADDRESS = 28; public static final byte DHCP_BROADCAST_ADDRESS = 28; protected Inet4Address mBroadcastAddress; protected Inet4Address mBroadcastAddress; /** /** * DHCP Optional Type: Vendor specific information * DHCP Optional Type: Vendor specific information */ */ protected static final byte DHCP_VENDOR_INFO = 43; public static final byte DHCP_VENDOR_INFO = 43; protected String mVendorInfo; protected String mVendorInfo; /** /** Loading @@ -215,7 +215,7 @@ public abstract class DhcpPacket { /** /** * DHCP Optional Type: Option overload option * DHCP Optional Type: Option overload option */ */ protected static final byte DHCP_OPTION_OVERLOAD = 52; public static final byte DHCP_OPTION_OVERLOAD = 52; /** /** * Possible values of the option overload option. * Possible values of the option overload option. Loading @@ -227,14 +227,14 @@ public abstract class DhcpPacket { /** /** * DHCP Optional Type: DHCP Requested IP Address * DHCP Optional Type: DHCP Requested IP Address */ */ protected static final byte DHCP_REQUESTED_IP = 50; public static final byte DHCP_REQUESTED_IP = 50; @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) public Inet4Address mRequestedIp; public Inet4Address mRequestedIp; /** /** * DHCP Optional Type: DHCP Lease Time * DHCP Optional Type: DHCP Lease Time */ */ protected static final byte DHCP_LEASE_TIME = 51; public static final byte DHCP_LEASE_TIME = 51; protected Integer mLeaseTime; protected Integer mLeaseTime; /** /** Loading @@ -254,72 +254,71 @@ public abstract class DhcpPacket { /** /** * DHCP Optional Type: DHCP Server Identifier * DHCP Optional Type: DHCP Server Identifier */ */ protected static final byte DHCP_SERVER_IDENTIFIER = 54; public static final byte DHCP_SERVER_IDENTIFIER = 54; @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) public Inet4Address mServerIdentifier; public Inet4Address mServerIdentifier; /** /** * DHCP Optional Type: DHCP Parameter List * DHCP Optional Type: DHCP Parameter List */ */ protected static final byte DHCP_PARAMETER_LIST = 55; public static final byte DHCP_PARAMETER_LIST = 55; protected byte[] mRequestedParams; protected byte[] mRequestedParams; /** /** * DHCP Optional Type: DHCP MESSAGE * DHCP Optional Type: DHCP MESSAGE */ */ protected static final byte DHCP_MESSAGE = 56; public static final byte DHCP_MESSAGE = 56; protected String mMessage; protected String mMessage; /** /** * DHCP Optional Type: Maximum DHCP Message Size * DHCP Optional Type: Maximum DHCP Message Size */ */ protected static final byte DHCP_MAX_MESSAGE_SIZE = 57; public static final byte DHCP_MAX_MESSAGE_SIZE = 57; protected Short mMaxMessageSize; protected Short mMaxMessageSize; /** /** * DHCP Optional Type: DHCP Renewal Time Value * DHCP Optional Type: DHCP Renewal Time Value */ */ protected static final byte DHCP_RENEWAL_TIME = 58; public static final byte DHCP_RENEWAL_TIME = 58; protected Integer mT1; protected Integer mT1; /** /** * DHCP Optional Type: Rebinding Time Value * DHCP Optional Type: Rebinding Time Value */ */ protected static final byte DHCP_REBINDING_TIME = 59; public static final byte DHCP_REBINDING_TIME = 59; protected Integer mT2; protected Integer mT2; /** /** * DHCP Optional Type: Vendor Class Identifier * DHCP Optional Type: Vendor Class Identifier */ */ protected static final byte DHCP_VENDOR_CLASS_ID = 60; public static final byte DHCP_VENDOR_CLASS_ID = 60; protected String mVendorId; protected String mVendorId; /** /** * DHCP Optional Type: DHCP Client Identifier * DHCP Optional Type: DHCP Client Identifier */ */ protected static final byte DHCP_CLIENT_IDENTIFIER = 61; public static final byte DHCP_CLIENT_IDENTIFIER = 61; protected byte[] mClientId; protected byte[] mClientId; /** /** * DHCP zero-length Optional Type: Rapid Commit. Per RFC4039, both DHCPDISCOVER and DHCPACK * DHCP zero-length Optional Type: Rapid Commit. Per RFC4039, both DHCPDISCOVER and DHCPACK * packet may include this option. * packet may include this option. */ */ protected static final byte DHCP_RAPID_COMMIT = 80; public static final byte DHCP_RAPID_COMMIT = 80; protected boolean mRapidCommit; protected boolean mRapidCommit; @VisibleForTesting public static final byte DHCP_CAPTIVE_PORTAL = (byte) 114; public static final byte DHCP_CAPTIVE_PORTAL = (byte) 114; protected String mCaptivePortalUrl; protected String mCaptivePortalUrl; /** /** * DHCP zero-length option code: pad * DHCP zero-length option code: pad */ */ protected static final byte DHCP_OPTION_PAD = 0x00; public static final byte DHCP_OPTION_PAD = 0x00; /** /** * DHCP zero-length option code: end of options * DHCP zero-length option code: end of options */ */ protected static final byte DHCP_OPTION_END = (byte) 0xff; public static final byte DHCP_OPTION_END = (byte) 0xff; /** /** * The transaction identifier used in this particular DHCP negotiation * The transaction identifier used in this particular DHCP negotiation Loading
tests/integration/src/android/net/ip/IpClientIntegrationTest.java +20 −72 Original line number Original line Diff line number Diff line Loading @@ -109,19 +109,16 @@ import android.net.shared.ProvisioningConfiguration.ScanResultInfo; import android.net.util.InterfaceParams; import android.net.util.InterfaceParams; import android.net.util.IpUtils; import android.net.util.IpUtils; import android.net.util.NetworkStackUtils; import android.net.util.NetworkStackUtils; import android.net.util.PacketReader; import android.os.Build; import android.os.Build; import android.os.Handler; import android.os.Handler; import android.os.HandlerThread; import android.os.HandlerThread; import android.os.IBinder; import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.PowerManager; import android.os.PowerManager; import android.os.RemoteException; import android.os.RemoteException; import android.os.SystemProperties; import android.os.SystemProperties; import android.system.ErrnoException; import android.system.ErrnoException; import android.system.Os; import android.system.Os; import androidx.annotation.Nullable; import androidx.test.InstrumentationRegistry; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import androidx.test.runner.AndroidJUnit4; Loading @@ -134,6 +131,7 @@ import com.android.server.NetworkObserverRegistry; import com.android.server.NetworkStackService.NetworkStackServiceManager; import com.android.server.NetworkStackService.NetworkStackServiceManager; import com.android.server.connectivity.ipmemorystore.IpMemoryStoreService; import com.android.server.connectivity.ipmemorystore.IpMemoryStoreService; import com.android.testutils.HandlerUtilsKt; import com.android.testutils.HandlerUtilsKt; import com.android.testutils.TapPacketReader; import org.junit.After; import org.junit.After; import org.junit.Before; import org.junit.Before; Loading @@ -145,7 +143,6 @@ import org.mockito.MockitoAnnotations; import org.mockito.Spy; import org.mockito.Spy; import java.io.FileDescriptor; import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.IOException; import java.io.IOException; import java.net.Inet4Address; import java.net.Inet4Address; import java.net.InetAddress; import java.net.InetAddress; Loading @@ -159,8 +156,6 @@ import java.util.HashMap; import java.util.List; import java.util.List; import java.util.Objects; import java.util.Objects; import java.util.Random; import java.util.Random; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; /** /** * Tests for IpClient. * Tests for IpClient. Loading Loading @@ -192,6 +187,7 @@ public class IpClientIntegrationTest { private HandlerThread mPacketReaderThread; private HandlerThread mPacketReaderThread; private Handler mHandler; private Handler mHandler; private TapPacketReader mPacketReader; private TapPacketReader mPacketReader; private FileDescriptor mTapFd; private IpClient mIpc; private IpClient mIpc; private Dependencies mDependencies; private Dependencies mDependencies; private byte[] mClientMac; private byte[] mClientMac; Loading Loading @@ -238,46 +234,6 @@ public class IpClientIntegrationTest { }; }; private static final byte TEST_VENDOR_SPECIFIC_TYPE = 0x06; private static final byte TEST_VENDOR_SPECIFIC_TYPE = 0x06; private static class TapPacketReader extends PacketReader { private final ParcelFileDescriptor mTapFd; private final LinkedBlockingQueue<byte[]> mReceivedPackets = new LinkedBlockingQueue<byte[]>(); TapPacketReader(Handler h, ParcelFileDescriptor tapFd) { super(h, DATA_BUFFER_LEN); mTapFd = tapFd; } @Override protected FileDescriptor createFd() { return mTapFd.getFileDescriptor(); } @Override protected void handlePacket(byte[] recvbuf, int length) { final byte[] newPacket = Arrays.copyOf(recvbuf, length); try { mReceivedPackets.put(newPacket); } catch (InterruptedException e) { fail("fail to put the new packet in the queue"); } } /** * Get the next packet that was received on the interface. * */ @Nullable public byte[] popPacket(long timeoutMs) { try { return mReceivedPackets.poll(timeoutMs, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { // Fall through } return null; } } private class Dependencies extends IpClient.Dependencies { private class Dependencies extends IpClient.Dependencies { private boolean mIsDhcpLeaseCacheEnabled; private boolean mIsDhcpLeaseCacheEnabled; private boolean mIsDhcpRapidCommitEnabled; private boolean mIsDhcpRapidCommitEnabled; Loading Loading @@ -411,6 +367,7 @@ public class IpClientIntegrationTest { public void tearDown() throws Exception { public void tearDown() throws Exception { if (mPacketReader != null) { if (mPacketReader != null) { mHandler.post(() -> mPacketReader.stop()); // Also closes the socket mHandler.post(() -> mPacketReader.stop()); // Also closes the socket mTapFd = null; } } if (mPacketReaderThread != null) { if (mPacketReaderThread != null) { mPacketReaderThread.quitSafely(); mPacketReaderThread.quitSafely(); Loading Loading @@ -440,8 +397,8 @@ public class IpClientIntegrationTest { mPacketReaderThread.start(); mPacketReaderThread.start(); mHandler = mPacketReaderThread.getThreadHandler(); mHandler = mPacketReaderThread.getThreadHandler(); final ParcelFileDescriptor tapFd = iface.getFileDescriptor(); mTapFd = iface.getFileDescriptor().getFileDescriptor(); mPacketReader = new TapPacketReader(mHandler, tapFd); mPacketReader = new TapPacketReader(mHandler, mTapFd, DATA_BUFFER_LEN); mHandler.post(() -> mPacketReader.start()); mHandler.post(() -> mPacketReader.start()); } } Loading Loading @@ -532,21 +489,12 @@ public class IpClientIntegrationTest { false /* broadcast */, "duplicated request IP address"); false /* broadcast */, "duplicated request IP address"); } } private void sendResponse(final ByteBuffer packet) throws IOException { try (FileOutputStream out = new FileOutputStream(mPacketReader.createFd())) { byte[] packetBytes = new byte[packet.limit()]; packet.get(packetBytes); packet.flip(); // So we can reuse it in the future. out.write(packetBytes); } } private void sendArpReply(final byte[] clientMac) throws IOException { private void sendArpReply(final byte[] clientMac) throws IOException { final ByteBuffer packet = ArpPacket.buildArpPacket(clientMac /* dst */, final ByteBuffer packet = ArpPacket.buildArpPacket(clientMac /* dst */, SERVER_MAC /* src */, INADDR_ANY.getAddress() /* target IP */, SERVER_MAC /* src */, INADDR_ANY.getAddress() /* target IP */, clientMac /* target HW address */, CLIENT_ADDR.getAddress() /* sender IP */, clientMac /* target HW address */, CLIENT_ADDR.getAddress() /* sender IP */, (short) ARP_REPLY); (short) ARP_REPLY); sendResponse(packet); mPacketReader.sendResponse(packet); } } private void sendArpProbe() throws IOException { private void sendArpProbe() throws IOException { Loading @@ -554,7 +502,7 @@ public class IpClientIntegrationTest { SERVER_MAC /* src */, CLIENT_ADDR.getAddress() /* target IP */, SERVER_MAC /* src */, CLIENT_ADDR.getAddress() /* target IP */, new byte[ETHER_ADDR_LEN] /* target HW address */, new byte[ETHER_ADDR_LEN] /* target HW address */, INADDR_ANY.getAddress() /* sender IP */, (short) ARP_REQUEST); INADDR_ANY.getAddress() /* sender IP */, (short) ARP_REQUEST); sendResponse(packet); mPacketReader.sendResponse(packet); } } private void startIpClientProvisioning(final boolean isDhcpLeaseCacheEnabled, private void startIpClientProvisioning(final boolean isDhcpLeaseCacheEnabled, Loading Loading @@ -667,18 +615,18 @@ public class IpClientIntegrationTest { packetList.add(packet); packetList.add(packet); if (packet instanceof DhcpDiscoverPacket) { if (packet instanceof DhcpDiscoverPacket) { if (shouldReplyRapidCommitAck) { if (shouldReplyRapidCommitAck) { sendResponse(buildDhcpAckPacket(packet, leaseTimeSec, (short) mtu, mPacketReader.sendResponse(buildDhcpAckPacket(packet, leaseTimeSec, (short) mtu, true /* rapidCommit */, captivePortalApiUrl)); true /* rapidCommit */, captivePortalApiUrl)); } else { } else { sendResponse(buildDhcpOfferPacket(packet, leaseTimeSec, (short) mtu, mPacketReader.sendResponse(buildDhcpOfferPacket(packet, leaseTimeSec, captivePortalApiUrl)); (short) mtu, captivePortalApiUrl)); } } } else if (packet instanceof DhcpRequestPacket) { } else if (packet instanceof DhcpRequestPacket) { final ByteBuffer byteBuffer = isSuccessLease final ByteBuffer byteBuffer = isSuccessLease ? buildDhcpAckPacket(packet, leaseTimeSec, (short) mtu, ? buildDhcpAckPacket(packet, leaseTimeSec, (short) mtu, false /* rapidCommit */, captivePortalApiUrl) false /* rapidCommit */, captivePortalApiUrl) : buildDhcpNakPacket(packet); : buildDhcpNakPacket(packet); sendResponse(byteBuffer); mPacketReader.sendResponse(byteBuffer); } else { } else { fail("invalid DHCP packet"); fail("invalid DHCP packet"); } } Loading Loading @@ -777,7 +725,7 @@ public class IpClientIntegrationTest { assertEquals(NetworkInterface.getByName(mIfaceName).getMTU(), mtu); assertEquals(NetworkInterface.getByName(mIfaceName).getMTU(), mtu); } } if (shouldRemoveTapInterface) removeTapInterface(mPacketReader.createFd()); if (shouldRemoveTapInterface) removeTapInterface(mTapFd); try { try { mIpc.shutdown(); mIpc.shutdown(); awaitIpClientShutdown(); awaitIpClientShutdown(); Loading Loading @@ -845,12 +793,12 @@ public class IpClientIntegrationTest { final short mtu = (short) TEST_DEFAULT_MTU; final short mtu = (short) TEST_DEFAULT_MTU; if (!shouldReplyRapidCommitAck) { if (!shouldReplyRapidCommitAck) { sendResponse(buildDhcpOfferPacket(packet, TEST_LEASE_DURATION_S, mtu, mPacketReader.sendResponse(buildDhcpOfferPacket(packet, TEST_LEASE_DURATION_S, mtu, null /* captivePortalUrl */)); null /* captivePortalUrl */)); packet = getNextDhcpPacket(); packet = getNextDhcpPacket(); assertTrue(packet instanceof DhcpRequestPacket); assertTrue(packet instanceof DhcpRequestPacket); } } sendResponse(buildDhcpAckPacket(packet, TEST_LEASE_DURATION_S, mtu, mPacketReader.sendResponse(buildDhcpAckPacket(packet, TEST_LEASE_DURATION_S, mtu, shouldReplyRapidCommitAck, null /* captivePortalUrl */)); shouldReplyRapidCommitAck, null /* captivePortalUrl */)); if (!shouldAbortPreconnection) { if (!shouldAbortPreconnection) { Loading Loading @@ -1126,7 +1074,7 @@ public class IpClientIntegrationTest { @Test @Test public void testRestoreInitialInterfaceMtu_NotFoundInterfaceWhenStartingProvisioning() public void testRestoreInitialInterfaceMtu_NotFoundInterfaceWhenStartingProvisioning() throws Exception { throws Exception { removeTapInterface(mPacketReader.createFd()); removeTapInterface(mTapFd); ProvisioningConfiguration config = new ProvisioningConfiguration.Builder() ProvisioningConfiguration config = new ProvisioningConfiguration.Builder() .withoutIpReachabilityMonitor() .withoutIpReachabilityMonitor() .withoutIPv6() .withoutIPv6() Loading Loading @@ -1284,7 +1232,7 @@ public class IpClientIntegrationTest { ByteBuffer ra = buildRaPacket(pio, rdnss1, rdnss2); ByteBuffer ra = buildRaPacket(pio, rdnss1, rdnss2); waitForRouterSolicitation(); waitForRouterSolicitation(); sendResponse(ra); mPacketReader.sendResponse(ra); ArgumentCaptor<LinkProperties> captor = ArgumentCaptor.forClass(LinkProperties.class); ArgumentCaptor<LinkProperties> captor = ArgumentCaptor.forClass(LinkProperties.class); verify(mCb, timeout(TEST_TIMEOUT_MS)).onProvisioningSuccess(captor.capture()); verify(mCb, timeout(TEST_TIMEOUT_MS)).onProvisioningSuccess(captor.capture()); Loading @@ -1299,7 +1247,7 @@ public class IpClientIntegrationTest { // If the RDNSS lifetime is above the minimum, the DNS server is accepted. // If the RDNSS lifetime is above the minimum, the DNS server is accepted. rdnss1 = buildRdnssOption(68, lowlifeDnsServer); rdnss1 = buildRdnssOption(68, lowlifeDnsServer); ra = buildRaPacket(pio, rdnss1, rdnss2); ra = buildRaPacket(pio, rdnss1, rdnss2); sendResponse(ra); mPacketReader.sendResponse(ra); verify(mCb, timeout(TEST_TIMEOUT_MS)).onLinkPropertiesChange(captor.capture()); verify(mCb, timeout(TEST_TIMEOUT_MS)).onLinkPropertiesChange(captor.capture()); lp = captor.getValue(); lp = captor.getValue(); assertNotNull(lp); assertNotNull(lp); Loading @@ -1312,7 +1260,7 @@ public class IpClientIntegrationTest { rdnss1 = buildRdnssOption(0, dnsServer); rdnss1 = buildRdnssOption(0, dnsServer); rdnss2 = buildRdnssOption(0, lowlifeDnsServer); rdnss2 = buildRdnssOption(0, lowlifeDnsServer); ra = buildRaPacket(pio, rdnss1, rdnss2); ra = buildRaPacket(pio, rdnss1, rdnss2); sendResponse(ra); mPacketReader.sendResponse(ra); verify(mCb, timeout(TEST_TIMEOUT_MS)).onProvisioningFailure(captor.capture()); verify(mCb, timeout(TEST_TIMEOUT_MS)).onProvisioningFailure(captor.capture()); lp = captor.getValue(); lp = captor.getValue(); Loading Loading @@ -1546,8 +1494,8 @@ public class IpClientIntegrationTest { // Send Offer and handle Request -> Ack // Send Offer and handle Request -> Ack final String serverSentUrl = serverSendsOption ? TEST_CAPTIVE_PORTAL_URL : null; final String serverSentUrl = serverSendsOption ? TEST_CAPTIVE_PORTAL_URL : null; sendResponse(buildDhcpOfferPacket(discover, TEST_LEASE_DURATION_S, (short) TEST_DEFAULT_MTU, mPacketReader.sendResponse(buildDhcpOfferPacket(discover, TEST_LEASE_DURATION_S, serverSentUrl)); (short) TEST_DEFAULT_MTU, serverSentUrl)); final int testMtu = 1345; final int testMtu = 1345; handleDhcpPackets(true /* isSuccessLease */, TEST_LEASE_DURATION_S, handleDhcpPackets(true /* isSuccessLease */, TEST_LEASE_DURATION_S, false /* isDhcpRapidCommitEnabled */, testMtu, false /* isDhcpRapidCommitEnabled */, testMtu, Loading
tests/lib/Android.bp +4 −0 Original line number Original line Diff line number Diff line Loading @@ -32,8 +32,12 @@ java_library { srcs: [ srcs: [ "src/**/*.java", "src/**/*.java", "src/**/*.kt", "src/**/*.kt", ":net-module-utils-srcs-for-tests", ], ], defaults: ["lib_mockito_extended"], defaults: ["lib_mockito_extended"], libs: [ "androidx.annotation_annotation", ], static_libs: [ static_libs: [ "net-tests-utils-multivariant", "net-tests-utils-multivariant", ], ], Loading
tests/lib/src/com/android/testutils/TapPacketReader.java 0 → 100644 +76 −0 Original line number Original line 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 com.android.testutils; import android.net.util.PacketReader; import android.os.Handler; import androidx.annotation.Nullable; import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; public class TapPacketReader extends PacketReader { private final FileDescriptor mTapFd; private final LinkedBlockingQueue<byte[]> mReceivedPackets = new LinkedBlockingQueue<byte[]>(); public TapPacketReader(Handler h, FileDescriptor tapFd, int maxPacketSize) { super(h, maxPacketSize); mTapFd = tapFd; } @Override protected FileDescriptor createFd() { return mTapFd; } @Override protected void handlePacket(byte[] recvbuf, int length) { final byte[] newPacket = Arrays.copyOf(recvbuf, length); if (!mReceivedPackets.offer(newPacket)) { throw new AssertionError("More than " + Integer.MAX_VALUE + " packets outstanding!"); } } /** * Get the next packet that was received on the interface. * */ @Nullable public byte[] popPacket(long timeoutMs) { try { return mReceivedPackets.poll(timeoutMs, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { // Fall through } return null; } public void sendResponse(final ByteBuffer packet) throws IOException { try (FileOutputStream out = new FileOutputStream(mTapFd)) { byte[] packetBytes = new byte[packet.limit()]; packet.get(packetBytes); packet.flip(); // So we can reuse it in the future. out.write(packetBytes); } } }