Loading services/net/java/android/net/apf/ApfFilter.java +22 −10 Original line number Diff line number Diff line Loading @@ -289,8 +289,15 @@ public class ApfFilter { return System.currentTimeMillis() / DateUtils.SECOND_IN_MILLIS; } public static class InvalidRaException extends Exception { public InvalidRaException(String m) { super(m); } } // A class to hold information about an RA. private class Ra { @VisibleForTesting class Ra { // From RFC4861: private static final int ICMP6_RA_HEADER_LEN = 16; private static final int ICMP6_RA_CHECKSUM_OFFSET = Loading Loading @@ -436,7 +443,11 @@ public class ApfFilter { // Buffer.position(int) or due to an invalid-length option) or IndexOutOfBoundsException // (from ByteBuffer.get(int) ) if parsing encounters something non-compliant with // specifications. Ra(byte[] packet, int length) { Ra(byte[] packet, int length) throws InvalidRaException { if (length < ICMP6_RA_OPTION_OFFSET) { throw new InvalidRaException("Not an ICMP6 router advertisement"); } mPacket = ByteBuffer.wrap(Arrays.copyOf(packet, length)); mLastSeen = curTime(); Loading @@ -445,7 +456,7 @@ public class ApfFilter { if (getUint16(mPacket, ETH_ETHERTYPE_OFFSET) != ETH_P_IPV6 || uint8(mPacket.get(IPV6_NEXT_HEADER_OFFSET)) != IPPROTO_ICMPV6 || uint8(mPacket.get(ICMP6_TYPE_OFFSET)) != ICMP6_ROUTER_ADVERTISEMENT) { throw new IllegalArgumentException("Not an ICMP6 router advertisement"); throw new InvalidRaException("Not an ICMP6 router advertisement"); } Loading Loading @@ -511,7 +522,7 @@ public class ApfFilter { break; } if (optionLength <= 0) { throw new IllegalArgumentException(String.format( throw new InvalidRaException(String.format( "Invalid option length opt=%d len=%d", optionType, optionLength)); } mPacket.position(position + optionLength); Loading Loading @@ -925,8 +936,8 @@ public class ApfFilter { // Execution will reach the end of the program if no filters match, which will pass the // packet to the AP. program = gen.generate(); } catch (IllegalInstructionException e) { Log.e(TAG, "Program failed to generate: ", e); } catch (IllegalInstructionException|IllegalStateException e) { Log.e(TAG, "Failed to generate APF program.", e); return; } mLastTimeInstalledProgram = curTime(); Loading Loading @@ -972,7 +983,8 @@ public class ApfFilter { * if the current APF program should be updated. * @return a ProcessRaResult enum describing what action was performed. */ private synchronized ProcessRaResult processRa(byte[] packet, int length) { @VisibleForTesting synchronized ProcessRaResult processRa(byte[] packet, int length) { if (VDBG) hexDump("Read packet = ", packet, length); // Have we seen this RA before? Loading Loading @@ -1011,7 +1023,7 @@ public class ApfFilter { try { ra = new Ra(packet, length); } catch (Exception e) { Log.e(TAG, "Error parsing RA: " + e); Log.e(TAG, "Error parsing RA", e); return ProcessRaResult.PARSE_ERROR; } // Ignore 0 lifetime RAs. Loading services/tests/servicestests/src/android/net/apf/ApfTest.java +38 −4 Original line number Diff line number Diff line Loading @@ -16,10 +16,6 @@ package android.net.apf; import static android.system.OsConstants.*; import com.android.frameworks.servicestests.R; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.NetworkUtils; Loading @@ -37,6 +33,10 @@ import android.system.ErrnoException; import android.system.Os; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.LargeTest; import static android.system.OsConstants.*; import com.android.frameworks.servicestests.R; import com.android.internal.util.HexDump; import org.mockito.ArgumentCaptor; import org.mockito.Mock; Loading @@ -54,6 +54,7 @@ import java.net.InetAddress; import java.net.NetworkInterface; import java.nio.ByteBuffer; import java.util.List; import java.util.Random; import libcore.io.IoUtils; import libcore.io.Streams; Loading Loading @@ -1146,6 +1147,39 @@ public class ApfTest extends AndroidTestCase { buffer.position(original); } public void testRaParsing() throws Exception { final int maxRandomPacketSize = 512; final Random r = new Random(); MockIpManagerCallback cb = new MockIpManagerCallback(); TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST, mLog); for (int i = 0; i < 1000; i++) { byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)]; r.nextBytes(packet); try { apfFilter.new Ra(packet, packet.length); } catch (ApfFilter.InvalidRaException e) { } catch (Exception e) { throw new Exception("bad packet: " + HexDump.toHexString(packet), e); } } } public void testRaProcessing() throws Exception { final int maxRandomPacketSize = 512; final Random r = new Random(); MockIpManagerCallback cb = new MockIpManagerCallback(); TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST, mLog); for (int i = 0; i < 1000; i++) { byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)]; r.nextBytes(packet); try { apfFilter.processRa(packet, packet.length); } catch (Exception e) { throw new Exception("bad packet: " + HexDump.toHexString(packet), e); } } } /** * Call the APF interpreter the run {@code program} on {@code packet} pretending the * filter was installed {@code filter_age} seconds ago. Loading Loading
services/net/java/android/net/apf/ApfFilter.java +22 −10 Original line number Diff line number Diff line Loading @@ -289,8 +289,15 @@ public class ApfFilter { return System.currentTimeMillis() / DateUtils.SECOND_IN_MILLIS; } public static class InvalidRaException extends Exception { public InvalidRaException(String m) { super(m); } } // A class to hold information about an RA. private class Ra { @VisibleForTesting class Ra { // From RFC4861: private static final int ICMP6_RA_HEADER_LEN = 16; private static final int ICMP6_RA_CHECKSUM_OFFSET = Loading Loading @@ -436,7 +443,11 @@ public class ApfFilter { // Buffer.position(int) or due to an invalid-length option) or IndexOutOfBoundsException // (from ByteBuffer.get(int) ) if parsing encounters something non-compliant with // specifications. Ra(byte[] packet, int length) { Ra(byte[] packet, int length) throws InvalidRaException { if (length < ICMP6_RA_OPTION_OFFSET) { throw new InvalidRaException("Not an ICMP6 router advertisement"); } mPacket = ByteBuffer.wrap(Arrays.copyOf(packet, length)); mLastSeen = curTime(); Loading @@ -445,7 +456,7 @@ public class ApfFilter { if (getUint16(mPacket, ETH_ETHERTYPE_OFFSET) != ETH_P_IPV6 || uint8(mPacket.get(IPV6_NEXT_HEADER_OFFSET)) != IPPROTO_ICMPV6 || uint8(mPacket.get(ICMP6_TYPE_OFFSET)) != ICMP6_ROUTER_ADVERTISEMENT) { throw new IllegalArgumentException("Not an ICMP6 router advertisement"); throw new InvalidRaException("Not an ICMP6 router advertisement"); } Loading Loading @@ -511,7 +522,7 @@ public class ApfFilter { break; } if (optionLength <= 0) { throw new IllegalArgumentException(String.format( throw new InvalidRaException(String.format( "Invalid option length opt=%d len=%d", optionType, optionLength)); } mPacket.position(position + optionLength); Loading Loading @@ -925,8 +936,8 @@ public class ApfFilter { // Execution will reach the end of the program if no filters match, which will pass the // packet to the AP. program = gen.generate(); } catch (IllegalInstructionException e) { Log.e(TAG, "Program failed to generate: ", e); } catch (IllegalInstructionException|IllegalStateException e) { Log.e(TAG, "Failed to generate APF program.", e); return; } mLastTimeInstalledProgram = curTime(); Loading Loading @@ -972,7 +983,8 @@ public class ApfFilter { * if the current APF program should be updated. * @return a ProcessRaResult enum describing what action was performed. */ private synchronized ProcessRaResult processRa(byte[] packet, int length) { @VisibleForTesting synchronized ProcessRaResult processRa(byte[] packet, int length) { if (VDBG) hexDump("Read packet = ", packet, length); // Have we seen this RA before? Loading Loading @@ -1011,7 +1023,7 @@ public class ApfFilter { try { ra = new Ra(packet, length); } catch (Exception e) { Log.e(TAG, "Error parsing RA: " + e); Log.e(TAG, "Error parsing RA", e); return ProcessRaResult.PARSE_ERROR; } // Ignore 0 lifetime RAs. Loading
services/tests/servicestests/src/android/net/apf/ApfTest.java +38 −4 Original line number Diff line number Diff line Loading @@ -16,10 +16,6 @@ package android.net.apf; import static android.system.OsConstants.*; import com.android.frameworks.servicestests.R; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.NetworkUtils; Loading @@ -37,6 +33,10 @@ import android.system.ErrnoException; import android.system.Os; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.LargeTest; import static android.system.OsConstants.*; import com.android.frameworks.servicestests.R; import com.android.internal.util.HexDump; import org.mockito.ArgumentCaptor; import org.mockito.Mock; Loading @@ -54,6 +54,7 @@ import java.net.InetAddress; import java.net.NetworkInterface; import java.nio.ByteBuffer; import java.util.List; import java.util.Random; import libcore.io.IoUtils; import libcore.io.Streams; Loading Loading @@ -1146,6 +1147,39 @@ public class ApfTest extends AndroidTestCase { buffer.position(original); } public void testRaParsing() throws Exception { final int maxRandomPacketSize = 512; final Random r = new Random(); MockIpManagerCallback cb = new MockIpManagerCallback(); TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST, mLog); for (int i = 0; i < 1000; i++) { byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)]; r.nextBytes(packet); try { apfFilter.new Ra(packet, packet.length); } catch (ApfFilter.InvalidRaException e) { } catch (Exception e) { throw new Exception("bad packet: " + HexDump.toHexString(packet), e); } } } public void testRaProcessing() throws Exception { final int maxRandomPacketSize = 512; final Random r = new Random(); MockIpManagerCallback cb = new MockIpManagerCallback(); TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST, mLog); for (int i = 0; i < 1000; i++) { byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)]; r.nextBytes(packet); try { apfFilter.processRa(packet, packet.length); } catch (Exception e) { throw new Exception("bad packet: " + HexDump.toHexString(packet), e); } } } /** * Call the APF interpreter the run {@code program} on {@code packet} pretending the * filter was installed {@code filter_age} seconds ago. Loading