19132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen/* 29132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * Copyright (C) 2012 The Android Open Source Project 39132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * 49132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * Licensed under the Apache License, Version 2.0 (the "License"); 59132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * you may not use this file except in compliance with the License. 69132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * You may obtain a copy of the License at 79132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * 89132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * http://www.apache.org/licenses/LICENSE-2.0 99132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * 109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * Unless required by applicable law or agreed to in writing, software 119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * distributed under the License is distributed on an "AS IS" BASIS, 129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * See the License for the specific language governing permissions and 149132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * limitations under the License. 159132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen */ 169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 179132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenpackage android.net.apf; 189132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 197d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichiimport android.net.LinkAddress; 207d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichiimport android.net.LinkProperties; 217d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichiimport android.net.NetworkUtils; 229132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.net.apf.ApfCapabilities; 239132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.net.apf.ApfFilter; 249132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.net.apf.ApfGenerator; 259132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.net.apf.ApfGenerator.IllegalInstructionException; 269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.net.apf.ApfGenerator.Register; 279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.net.ip.IpManager; 286ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport android.net.metrics.IpConnectivityLog; 296ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport android.net.metrics.RaEvent; 309132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.os.ConditionVariable; 316ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport android.os.Parcelable; 324456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichiimport android.os.SystemClock; 339132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.system.ErrnoException; 349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.system.Os; 359132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.test.AndroidTestCase; 364456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichiimport android.text.format.DateUtils; 375d2654124e9e77dbda102a4435595c552cbc8e36Hugo Benichiimport android.test.suitebuilder.annotation.SmallTest; 380668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichiimport static android.system.OsConstants.*; 390668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi 407ceef950a02b22bdf90609bdab8119b4bcd88edfLorenzo Colittiimport com.android.frameworks.tests.net.R; 410668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichiimport com.android.internal.util.HexDump; 42495a17b332e57ea4c0162a4ae63d820b947e3719Hugo Benichiimport static com.android.internal.util.BitUtils.bytesToBEInt; 43495a17b332e57ea4c0162a4ae63d820b947e3719Hugo Benichiimport static com.android.internal.util.BitUtils.put; 449132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 456ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport org.mockito.ArgumentCaptor; 466ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport org.mockito.Mock; 476ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport org.mockito.MockitoAnnotations; 486ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport static org.mockito.Mockito.atLeastOnce; 496ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport static org.mockito.Mockito.verify; 506ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi 519132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.io.File; 529132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.io.FileDescriptor; 539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.io.FileOutputStream; 549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.io.IOException; 559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.io.InputStream; 569132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.io.OutputStream; 579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.net.InetAddress; 589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.net.NetworkInterface; 599132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.nio.ByteBuffer; 606ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport java.util.List; 610668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichiimport java.util.Random; 629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 639132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport libcore.io.IoUtils; 649132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport libcore.io.Streams; 659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen/** 679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * Tests for APF program generator and interpreter. 689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * 699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * Build, install and run with: 70495a17b332e57ea4c0162a4ae63d820b947e3719Hugo Benichi * runtest frameworks-net -c android.net.apf.ApfTest 719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen */ 729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenpublic class ApfTest extends AndroidTestCase { 739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int TIMEOUT_MS = 500; 749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 756ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi @Mock IpConnectivityLog mLog; 766ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi 779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen @Override 789132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen public void setUp() throws Exception { 799132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen super.setUp(); 806ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi MockitoAnnotations.initMocks(this); 819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Load up native shared library containing APF interpreter exposed via JNI. 827ceef950a02b22bdf90609bdab8119b4bcd88edfLorenzo Colitti System.loadLibrary("frameworksnettestsjni"); 839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Expected return codes from APF interpreter. 869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private final static int PASS = 1; 879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private final static int DROP = 0; 889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Interpreter will just accept packets without link layer headers, so pad fake packet to at 899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // least the minimum packet size. 909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private final static int MIN_PKT_SIZE = 15; 919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 926ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi private final static boolean DROP_MULTICAST = true; 936ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi private final static boolean ALLOW_MULTICAST = false; 946ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi 954dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy private final static boolean DROP_802_3_FRAMES = true; 964dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy private final static boolean ALLOW_802_3_FRAMES = false; 974dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy 98961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi private static String label(int code) { 99961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi switch (code) { 100961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi case PASS: return "PASS"; 101961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi case DROP: return "DROP"; 102961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi default: return "UNKNOWN"; 103961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi } 104961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi } 105961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi 106961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi private static void assertReturnCodesEqual(int expected, int got) { 107961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertEquals(label(expected), label(got)); 108961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi } 109961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi 1109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private void assertVerdict(int expected, byte[] program, byte[] packet, int filterAge) { 111961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertReturnCodesEqual(expected, apfSimulate(program, packet, filterAge)); 112961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi } 113961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi 114961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi private void assertVerdict(int expected, byte[] program, byte[] packet) { 115961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertReturnCodesEqual(expected, apfSimulate(program, packet, 0)); 1169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 1179132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 1189132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private void assertPass(byte[] program, byte[] packet, int filterAge) { 1199132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertVerdict(PASS, program, packet, filterAge); 1209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 1219132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 122961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi private void assertPass(byte[] program, byte[] packet) { 123961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertVerdict(PASS, program, packet); 124961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi } 125961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi 1269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private void assertDrop(byte[] program, byte[] packet, int filterAge) { 1279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertVerdict(DROP, program, packet, filterAge); 1289132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 1299132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 130961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi private void assertDrop(byte[] program, byte[] packet) { 131961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertVerdict(DROP, program, packet); 132961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi } 133961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi 1349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private void assertVerdict(int expected, ApfGenerator gen, byte[] packet, int filterAge) 1359132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen throws IllegalInstructionException { 136961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertReturnCodesEqual(expected, apfSimulate(gen.generate(), packet, filterAge)); 1379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 1389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 1399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private void assertPass(ApfGenerator gen, byte[] packet, int filterAge) 1409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen throws IllegalInstructionException { 1419132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertVerdict(PASS, gen, packet, filterAge); 1429132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 1439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 1449132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private void assertDrop(ApfGenerator gen, byte[] packet, int filterAge) 1459132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen throws IllegalInstructionException { 1469132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertVerdict(DROP, gen, packet, filterAge); 1479132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 1489132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 1499132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private void assertPass(ApfGenerator gen) 1509132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen throws IllegalInstructionException { 1519132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertVerdict(PASS, gen, new byte[MIN_PKT_SIZE], 0); 1529132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 1539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 1549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private void assertDrop(ApfGenerator gen) 1559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen throws IllegalInstructionException { 1569132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertVerdict(DROP, gen, new byte[MIN_PKT_SIZE], 0); 1579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 1589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 1599132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen /** 1609132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * Test each instruction by generating a program containing the instruction, 1619132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * generating bytecode for that program and running it through the 1629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * interpreter to verify it functions correctly. 1639132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen */ 164cfcc1cb7bf9caae440bf7c2c93efb43c9f90aa73Hugo Benichi @SmallTest 1659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen public void testApfInstructions() throws IllegalInstructionException { 1669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Empty program should pass because having the program counter reach the 1679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // location immediately after the program indicates the packet should be 1689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // passed to the AP. 1699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen ApfGenerator gen = new ApfGenerator(); 1709132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertPass(gen); 1719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 1729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test jumping to pass label. 1739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 1749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJump(gen.PASS_LABEL); 1759132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen byte[] program = gen.generate(); 1769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertEquals(1, program.length); 1779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertEquals((14 << 3) | (0 << 1) | 0, program[0]); 1789132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertPass(program, new byte[MIN_PKT_SIZE], 0); 1799132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 1809132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test jumping to drop label. 1819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 1829132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJump(gen.DROP_LABEL); 1839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen program = gen.generate(); 1849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertEquals(2, program.length); 1859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertEquals((14 << 3) | (1 << 1) | 0, program[0]); 1869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertEquals(1, program[1]); 1879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(program, new byte[15], 15); 1889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 1899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test jumping if equal to 0. 1909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 1919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(0, gen.DROP_LABEL); 1929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 1939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 1949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test jumping if not equal to 0. 1959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 1969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL); 1979132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertPass(gen); 1989132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 1999132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 1); 2009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL); 2019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 2029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 2039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test jumping if registers equal. 2049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 2059132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0EqualsR1(gen.DROP_LABEL); 2069132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 2079132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 2089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test jumping if registers not equal. 2099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 2109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL); 2119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertPass(gen); 2129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 2139132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 1); 2149132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL); 2159132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 2169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 2179132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test load immediate. 2189132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 2199132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 1234567890); 2209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL); 2219132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 2229132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 2239132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test add. 2249132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 2259132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addAdd(1234567890); 2269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL); 2279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 2289132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 2299132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test subtract. 2309132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 2319132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addAdd(-1234567890); 2329132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL); 2339132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 2349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 2359132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test or. 2369132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 2379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addOr(1234567890); 2389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL); 2399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 2409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 2419132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test and. 2429132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 2439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 1234567890); 2449132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addAnd(123456789); 2459132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL); 2469132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 2479132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 2489132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test left shift. 2499132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 2509132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 1234567890); 2519132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLeftShift(1); 2529132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL); 2539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 2549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 2559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test right shift. 2569132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 2579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 1234567890); 2589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addRightShift(1); 2599132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL); 2609132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 2619132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 2629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test multiply. 2639132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 2649132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 1234567890); 2659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addMul(2); 2669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(1234567890 * 2, gen.DROP_LABEL); 2679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 2689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 2699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test divide. 2709132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 2719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 1234567890); 2729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addDiv(2); 2739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL); 2749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 2759132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 2769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test divide by zero. 2779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 2789132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addDiv(0); 2799132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJump(gen.DROP_LABEL); 2809132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertPass(gen); 2819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 2829132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test add. 2839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 2849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R1, 1234567890); 2859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addAddR1(); 2869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL); 2879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 2889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 2899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test subtract. 2909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 2919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R1, -1234567890); 2929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addAddR1(); 2939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL); 2949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 2959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 2969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test or. 2979132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 2989132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R1, 1234567890); 2999132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addOrR1(); 3009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL); 3019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 3029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 3039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test and. 3049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 3059132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 1234567890); 3069132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R1, 123456789); 3079132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addAndR1(); 3089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL); 3099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 3109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 3119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test left shift. 3129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 3139132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 1234567890); 3149132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R1, 1); 3159132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLeftShiftR1(); 3169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL); 3179132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 3189132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 3199132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test right shift. 3209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 3219132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 1234567890); 3229132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R1, -1); 3239132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLeftShiftR1(); 3249132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL); 3259132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 3269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 3279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test multiply. 3289132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 3299132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 1234567890); 3309132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R1, 2); 3319132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addMulR1(); 3329132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(1234567890 * 2, gen.DROP_LABEL); 3339132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 3349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 3359132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test divide. 3369132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 3379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 1234567890); 3389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R1, 2); 3399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addDivR1(); 3409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL); 3419132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 3429132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 3439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test divide by zero. 3449132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 3459132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addDivR1(); 3469132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJump(gen.DROP_LABEL); 3479132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertPass(gen); 3489132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 3499132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test byte load. 3509132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 3519132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoad8(Register.R0, 1); 3529132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(45, gen.DROP_LABEL); 3539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0); 3549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 3559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test out of bounds load. 3569132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 3579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoad8(Register.R0, 16); 3589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(0, gen.DROP_LABEL); 3599132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0); 3609132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 3619132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test half-word load. 3629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 3639132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoad16(Register.R0, 1); 3649132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL); 3659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0); 3669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 3679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test word load. 3689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 3699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoad32(Register.R0, 1); 3709132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL); 3719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0); 3729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 3739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test byte indexed load. 3749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 3759132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R1, 1); 3769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoad8Indexed(Register.R0, 0); 3779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(45, gen.DROP_LABEL); 3789132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0); 3799132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 3809132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test out of bounds indexed load. 3819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 3829132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R1, 8); 3839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoad8Indexed(Register.R0, 8); 3849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(0, gen.DROP_LABEL); 3859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0); 3869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 3879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test half-word indexed load. 3889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 3899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R1, 1); 3909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoad16Indexed(Register.R0, 0); 3919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL); 3929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0); 3939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 3949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test word indexed load. 3959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 3969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R1, 1); 3979132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoad32Indexed(Register.R0, 0); 3989132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL); 3999132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0); 4009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 4019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test jumping if greater than. 4029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 4039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL); 4049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertPass(gen); 4059132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 4069132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 1); 4079132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL); 4089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 4099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 4109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test jumping if less than. 4119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 4129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0LessThan(0, gen.DROP_LABEL); 4139132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertPass(gen); 4149132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 4159132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0LessThan(1, gen.DROP_LABEL); 4169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 4179132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 4189132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test jumping if any bits set. 4199132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 4209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL); 4219132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertPass(gen); 4229132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 4239132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 1); 4249132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL); 4259132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 4269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 4279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 3); 4289132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL); 4299132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 4309132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 4319132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test jumping if register greater than. 4329132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 4339132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL); 4349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertPass(gen); 4359132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 4369132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 2); 4379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R1, 1); 4389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL); 4399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 4409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 4419132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test jumping if register less than. 4429132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 4439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0LessThanR1(gen.DROP_LABEL); 4449132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertPass(gen); 4459132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 4469132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R1, 1); 4479132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0LessThanR1(gen.DROP_LABEL); 4489132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 4499132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 4509132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test jumping if any bits set in register. 4519132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 4529132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R1, 3); 4539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL); 4549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertPass(gen); 4559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 4569132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R1, 3); 4579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 1); 4589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL); 4599132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 4609132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 4619132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R1, 3); 4629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 3); 4639132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL); 4649132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 4659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 4669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test load from memory. 4679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 4689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadFromMemory(Register.R0, 0); 4699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(0, gen.DROP_LABEL); 4709132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 4719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 4729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test store to memory. 4739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 4749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R1, 1234567890); 4759132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addStoreToMemory(Register.R1, 12); 4769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadFromMemory(Register.R0, 12); 4779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL); 4789132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 4799132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 4809132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test filter age pre-filled memory. 4819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 4829132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadFromMemory(Register.R0, gen.FILTER_AGE_MEMORY_SLOT); 4839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL); 4849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen, new byte[MIN_PKT_SIZE], 1234567890); 4859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 4869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test packet size pre-filled memory. 4879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 4889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadFromMemory(Register.R0, gen.PACKET_SIZE_MEMORY_SLOT); 4899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(MIN_PKT_SIZE, gen.DROP_LABEL); 4909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 4919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 4929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test IPv4 header size pre-filled memory. 4939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 4949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadFromMemory(Register.R0, gen.IPV4_HEADER_SIZE_MEMORY_SLOT); 4959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(20, gen.DROP_LABEL); 4969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen, new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x45}, 0); 4979132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 4989132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test not. 4999132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 5009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 1234567890); 5019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addNot(Register.R0); 5029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(~1234567890, gen.DROP_LABEL); 5039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 5049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 5059132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test negate. 5069132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 5079132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 1234567890); 5089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addNeg(Register.R0); 5099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL); 5109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 5119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 5129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test move. 5139132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 5149132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R1, 1234567890); 5159132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addMove(Register.R0); 5169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL); 5179132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 5189132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 5199132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 1234567890); 5209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addMove(Register.R1); 5219132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL); 5229132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 5239132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 5249132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test swap. 5259132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 5269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R1, 1234567890); 5279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addSwap(); 5289132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL); 5299132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 5309132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 5319132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 1234567890); 5329132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addSwap(); 5339132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfR0Equals(0, gen.DROP_LABEL); 5349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen); 5359132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 5369132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test jump if bytes not equal. 5379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 5389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 1); 5399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL); 5409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen program = gen.generate(); 5419132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertEquals(6, program.length); 5429132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertEquals((13 << 3) | (1 << 1) | 0, program[0]); 5439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertEquals(1, program[1]); 5449132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertEquals(((20 << 3) | (1 << 1) | 0) - 256, program[2]); 5459132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertEquals(1, program[3]); 5469132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertEquals(1, program[4]); 5479132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertEquals(123, program[5]); 5489132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(program, new byte[MIN_PKT_SIZE], 0); 5499132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 5509132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 1); 5519132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL); 552961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi byte[] packet123 = {0,123,0,0,0,0,0,0,0,0,0,0,0,0,0}; 5539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertPass(gen, packet123, 0); 5549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 5559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL); 5569132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen, packet123, 0); 5579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 5589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 1); 5599132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,30,4,5}, gen.DROP_LABEL); 560961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi byte[] packet12345 = {0,1,2,3,4,5,0,0,0,0,0,0,0,0,0}; 5619132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertDrop(gen, packet12345, 0); 5629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen = new ApfGenerator(); 5639132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addLoadImmediate(Register.R0, 1); 5649132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,3,4,5}, gen.DROP_LABEL); 5659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertPass(gen, packet12345, 0); 5669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 5679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 5689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen /** 5699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * Generate some BPF programs, translate them to APF, then run APF and BPF programs 5709132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * over packet traces and verify both programs filter out the same packets. 5719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen */ 572cfcc1cb7bf9caae440bf7c2c93efb43c9f90aa73Hugo Benichi @SmallTest 5739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen public void testApfAgainstBpf() throws Exception { 5749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen String[] tcpdump_filters = new String[]{ "udp", "tcp", "icmp", "icmp6", "udp port 53", 5759132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen "arp", "dst 239.255.255.250", "arp or tcp or udp port 53", "net 192.168.1.0/24", 5769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen "arp or icmp6 or portrange 53-54", "portrange 53-54 or portrange 100-50000", 5779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen "tcp[tcpflags] & (tcp-ack|tcp-fin) != 0 and (ip[2:2] > 57 or icmp)" }; 5789132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen String pcap_filename = stageFile(R.raw.apf); 5799132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen for (String tcpdump_filter : tcpdump_filters) { 5809132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen byte[] apf_program = Bpf2Apf.convert(compileToBpf(tcpdump_filter)); 5819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertTrue("Failed to match for filter: " + tcpdump_filter, 5829132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen compareBpfApf(tcpdump_filter, pcap_filename, apf_program)); 5839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 5849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 5859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 5869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private class MockIpManagerCallback extends IpManager.Callback { 5879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private final ConditionVariable mGotApfProgram = new ConditionVariable(); 5889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private byte[] mLastApfProgram; 5899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 5909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen @Override 5919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen public void installPacketFilter(byte[] filter) { 5929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen mLastApfProgram = filter; 5939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen mGotApfProgram.open(); 5949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 5959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 5969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen public void resetApfProgramWait() { 5979132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen mGotApfProgram.close(); 5989132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 5999132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 6009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen public byte[] getApfProgram() { 6019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertTrue(mGotApfProgram.block(TIMEOUT_MS)); 6029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen return mLastApfProgram; 6039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 6048995d85b9432387520c9f04a69251536754b996bLorenzo Colitti 6058995d85b9432387520c9f04a69251536754b996bLorenzo Colitti public void assertNoProgramUpdate() { 6068995d85b9432387520c9f04a69251536754b996bLorenzo Colitti assertFalse(mGotApfProgram.block(TIMEOUT_MS)); 6078995d85b9432387520c9f04a69251536754b996bLorenzo Colitti } 6089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 6099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 6109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static class TestApfFilter extends ApfFilter { 611961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi public final static byte[] MOCK_MAC_ADDR = {1,2,3,4,5,6}; 6129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private FileDescriptor mWriteSocket; 6139132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 6144456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi private final long mFixedTimeMs = SystemClock.elapsedRealtime(); 6154456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi 6166ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi public TestApfFilter(IpManager.Callback ipManagerCallback, boolean multicastFilter, 6174dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy boolean ieee802_3Filter, IpConnectivityLog log) throws Exception { 6180dc1d314709d579ccdc3fc59a5f66557f6cd319dHugo Benichi super(new ApfCapabilities(2, 1700, ARPHRD_ETHER), NetworkInterface.getByName("lo"), 6194dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy ipManagerCallback, multicastFilter, ieee802_3Filter, log); 6209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 6219132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 6229132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Pretend an RA packet has been received and show it to ApfFilter. 6239132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen public void pretendPacketReceived(byte[] packet) throws IOException, ErrnoException { 6249132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // ApfFilter's ReceiveThread will be waiting to read this. 6259132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen Os.write(mWriteSocket, packet, 0, packet.length); 6269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 6279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 6289132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen @Override 6294456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi protected long currentTimeSeconds() { 6304456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi return mFixedTimeMs / DateUtils.SECOND_IN_MILLIS; 6314456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi } 6324456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi 6334456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi @Override 6349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen void maybeStartFilter() { 6359132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen mHardwareAddress = MOCK_MAC_ADDR; 6369132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen installNewProgramLocked(); 6379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 6389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Create two sockets, "readSocket" and "mWriteSocket" and connect them together. 6399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen FileDescriptor readSocket = new FileDescriptor(); 6409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen mWriteSocket = new FileDescriptor(); 6419132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen try { 6429132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen Os.socketpair(AF_UNIX, SOCK_STREAM, 0, mWriteSocket, readSocket); 6439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } catch (ErrnoException e) { 6449132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen fail(); 6459132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen return; 6469132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 6479132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Now pass readSocket to ReceiveThread as if it was setup to read raw RAs. 6489132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // This allows us to pretend RA packets have been recieved via pretendPacketReceived(). 6499132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen mReceiveThread = new ReceiveThread(readSocket); 6509132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen mReceiveThread.start(); 6519132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 6529132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 6539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen @Override 6549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen public void shutdown() { 6559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen super.shutdown(); 6569132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen IoUtils.closeQuietly(mWriteSocket); 6579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 6589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 6599132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 6609132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int ETH_HEADER_LEN = 14; 66138db976514ff2ad12d207a927219762eab179882Hugo Benichi private static final int ETH_DEST_ADDR_OFFSET = 0; 6629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int ETH_ETHERTYPE_OFFSET = 12; 663961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi private static final byte[] ETH_BROADCAST_MAC_ADDRESS = 664961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff }; 6659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 6669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int IPV4_VERSION_IHL_OFFSET = ETH_HEADER_LEN + 0; 6679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int IPV4_PROTOCOL_OFFSET = ETH_HEADER_LEN + 9; 6689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int IPV4_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 16; 669961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi private static final byte[] IPV4_BROADCAST_ADDRESS = 670961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi {(byte) 255, (byte) 255, (byte) 255, (byte) 255}; 6719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 6729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int IPV6_NEXT_HEADER_OFFSET = ETH_HEADER_LEN + 6; 6739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int IPV6_HEADER_LEN = 40; 6749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int IPV6_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 24; 6759132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // The IPv6 all nodes address ff02::1 6769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final byte[] IPV6_ALL_NODES_ADDRESS = 677961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; 67802428988ad90a2bd294b9ce752c2fced5b649519Hugo Benichi private static final byte[] IPV6_ALL_ROUTERS_ADDRESS = 67902428988ad90a2bd294b9ce752c2fced5b649519Hugo Benichi { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 }; 6809132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 6819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int ICMP6_TYPE_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN; 68202428988ad90a2bd294b9ce752c2fced5b649519Hugo Benichi private static final int ICMP6_ROUTER_SOLICITATION = 133; 6839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int ICMP6_ROUTER_ADVERTISEMENT = 134; 68402428988ad90a2bd294b9ce752c2fced5b649519Hugo Benichi private static final int ICMP6_NEIGHBOR_SOLICITATION = 135; 6859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136; 6869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 6879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int ICMP6_RA_HEADER_LEN = 16; 6889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET = 6899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen ETH_HEADER_LEN + IPV6_HEADER_LEN + 6; 6909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int ICMP6_RA_CHECKSUM_OFFSET = 6919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen ETH_HEADER_LEN + IPV6_HEADER_LEN + 2; 6929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int ICMP6_RA_OPTION_OFFSET = 6939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen ETH_HEADER_LEN + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN; 6949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 6959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int ICMP6_PREFIX_OPTION_TYPE = 3; 6969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int ICMP6_PREFIX_OPTION_LEN = 32; 6979132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET = 4; 6989132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET = 8; 6999132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 7009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // From RFC6106: Recursive DNS Server option 7019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int ICMP6_RDNSS_OPTION_TYPE = 25; 7029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // From RFC6106: DNS Search List option 7039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int ICMP6_DNSSL_OPTION_TYPE = 31; 7049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 7059132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // From RFC4191: Route Information option 7069132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int ICMP6_ROUTE_INFO_OPTION_TYPE = 24; 7079132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Above three options all have the same format: 7089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int ICMP6_4_BYTE_OPTION_LEN = 8; 7099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int ICMP6_4_BYTE_LIFETIME_OFFSET = 4; 7109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int ICMP6_4_BYTE_LIFETIME_LEN = 4; 7119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 7129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int UDP_HEADER_LEN = 8; 7139132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int UDP_DESTINATION_PORT_OFFSET = ETH_HEADER_LEN + 22; 7149132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 7159132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int DHCP_CLIENT_PORT = 68; 7169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 48; 7179132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 7184fc3ee5be223122792ebc0ee8a05c93d93e26a52Hugo Benichi private static final int ARP_HEADER_OFFSET = ETH_HEADER_LEN; 719961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi private static final byte[] ARP_IPV4_REQUEST_HEADER = { 7209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 0, 1, // Hardware type: Ethernet (1) 7219132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 8, 0, // Protocol type: IP (0x0800) 7229132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 6, // Hardware size: 6 7239132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 4, // Protocol size: 4 7249132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 0, 1 // Opcode: request (1) 7259132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen }; 726961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi private static final byte[] ARP_IPV4_REPLY_HEADER = { 72738db976514ff2ad12d207a927219762eab179882Hugo Benichi 0, 1, // Hardware type: Ethernet (1) 72838db976514ff2ad12d207a927219762eab179882Hugo Benichi 8, 0, // Protocol type: IP (0x0800) 72938db976514ff2ad12d207a927219762eab179882Hugo Benichi 6, // Hardware size: 6 73038db976514ff2ad12d207a927219762eab179882Hugo Benichi 4, // Protocol size: 4 73138db976514ff2ad12d207a927219762eab179882Hugo Benichi 0, 2 // Opcode: reply (2) 73238db976514ff2ad12d207a927219762eab179882Hugo Benichi }; 7334fc3ee5be223122792ebc0ee8a05c93d93e26a52Hugo Benichi private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ETH_HEADER_LEN + 24; 7349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 735961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi private static final byte[] MOCK_IPV4_ADDR = {10, 0, 0, 1}; 7367d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi private static final byte[] MOCK_BROADCAST_IPV4_ADDR = {10, 0, 31, (byte) 255}; // prefix = 19 737961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi private static final byte[] MOCK_MULTICAST_IPV4_ADDR = {(byte) 224, 0, 0, 1}; 738961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi private static final byte[] ANOTHER_IPV4_ADDR = {10, 0, 0, 2}; 739961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi private static final byte[] IPV4_ANY_HOST_ADDR = {0, 0, 0, 0}; 7409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 741cfcc1cb7bf9caae440bf7c2c93efb43c9f90aa73Hugo Benichi @SmallTest 7429132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen public void testApfFilterIPv4() throws Exception { 7439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); 7447d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19); 7457d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi LinkProperties lp = new LinkProperties(); 7467d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi lp.addLinkAddress(link); 7470dc1d314709d579ccdc3fc59a5f66557f6cd319dHugo Benichi 7484dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, 7494dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy ALLOW_802_3_FRAMES, mLog); 7507d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi apfFilter.setLinkProperties(lp); 7510dc1d314709d579ccdc3fc59a5f66557f6cd319dHugo Benichi 7529132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen byte[] program = ipManagerCallback.getApfProgram(); 7539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 7549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Verify empty packet of 100 zero bytes is passed 7559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 756961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertPass(program, packet.array()); 7579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 7589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Verify unicast IPv4 packet is passed 759961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR); 7609132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 761961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_IPV4_ADDR); 762961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertPass(program, packet.array()); 763961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi 7640dc1d314709d579ccdc3fc59a5f66557f6cd319dHugo Benichi // Verify L2 unicast to IPv4 broadcast addresses is dropped (b/30231088) 765961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS); 7660dc1d314709d579ccdc3fc59a5f66557f6cd319dHugo Benichi assertDrop(program, packet.array()); 767961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR); 7687d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi assertDrop(program, packet.array()); 769961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi 770961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi // Verify multicast/broadcast IPv4, not DHCP to us, is dropped 771961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS); 772961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertDrop(program, packet.array()); 7739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen packet.put(IPV4_VERSION_IHL_OFFSET, (byte)0x45); 774961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertDrop(program, packet.array()); 7759132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen packet.put(IPV4_PROTOCOL_OFFSET, (byte)IPPROTO_UDP); 776961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertDrop(program, packet.array()); 7779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen packet.putShort(UDP_DESTINATION_PORT_OFFSET, (short)DHCP_CLIENT_PORT); 778961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertDrop(program, packet.array()); 779961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_MULTICAST_IPV4_ADDR); 780961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertDrop(program, packet.array()); 781961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR); 782961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertDrop(program, packet.array()); 783961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS); 784961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertDrop(program, packet.array()); 7859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 7869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Verify broadcast IPv4 DHCP to us is passed 787961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi put(packet, DHCP_CLIENT_MAC_OFFSET, TestApfFilter.MOCK_MAC_ADDR); 788961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertPass(program, packet.array()); 789961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi 790961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi // Verify unicast IPv4 DHCP to us is passed 791961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR); 792961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertPass(program, packet.array()); 7939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 7949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen apfFilter.shutdown(); 7959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 7969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 797cfcc1cb7bf9caae440bf7c2c93efb43c9f90aa73Hugo Benichi @SmallTest 7989132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen public void testApfFilterIPv6() throws Exception { 7999132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); 8004dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, 8014dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy ALLOW_802_3_FRAMES, mLog); 8029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen byte[] program = ipManagerCallback.getApfProgram(); 8039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 8049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Verify empty IPv6 packet is passed 8059132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 8069132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6); 807961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertPass(program, packet.array()); 8089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 8099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Verify empty ICMPv6 packet is passed 8109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6); 811961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertPass(program, packet.array()); 8129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 8139132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Verify empty ICMPv6 NA packet is passed 8149132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_NEIGHBOR_ANNOUNCEMENT); 815961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertPass(program, packet.array()); 8169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 8179132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Verify ICMPv6 NA to ff02::1 is dropped 818961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_NODES_ADDRESS); 819961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertDrop(program, packet.array()); 8209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 82102428988ad90a2bd294b9ce752c2fced5b649519Hugo Benichi // Verify ICMPv6 RS to any is dropped 82202428988ad90a2bd294b9ce752c2fced5b649519Hugo Benichi packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_SOLICITATION); 82302428988ad90a2bd294b9ce752c2fced5b649519Hugo Benichi assertDrop(program, packet.array()); 82402428988ad90a2bd294b9ce752c2fced5b649519Hugo Benichi put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_ROUTERS_ADDRESS); 82502428988ad90a2bd294b9ce752c2fced5b649519Hugo Benichi assertDrop(program, packet.array()); 82602428988ad90a2bd294b9ce752c2fced5b649519Hugo Benichi 8279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen apfFilter.shutdown(); 8289132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 8299132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 830cfcc1cb7bf9caae440bf7c2c93efb43c9f90aa73Hugo Benichi @SmallTest 83111e13e2175674389ed18c2b1e1af69c5ad931e8fLorenzo Colitti public void testApfFilterMulticast() throws Exception { 832961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi final byte[] unicastIpv4Addr = {(byte)192,0,2,63}; 8337d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi final byte[] broadcastIpv4Addr = {(byte)192,0,2,(byte)255}; 834961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi final byte[] multicastIpv4Addr = {(byte)224,0,0,1}; 835961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb}; 836961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi 8377d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); 8387d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi LinkAddress link = new LinkAddress(InetAddress.getByAddress(unicastIpv4Addr), 24); 8397d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi LinkProperties lp = new LinkProperties(); 8407d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi lp.addLinkAddress(link); 8417d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi 8424dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, 8434dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy DROP_802_3_FRAMES, mLog); 8447d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi apfFilter.setLinkProperties(lp); 8457d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi 8467d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi byte[] program = ipManagerCallback.getApfProgram(); 8477d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi 84811e13e2175674389ed18c2b1e1af69c5ad931e8fLorenzo Colitti // Construct IPv4 and IPv6 multicast packets. 849f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen ByteBuffer mcastv4packet = ByteBuffer.wrap(new byte[100]); 850f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen mcastv4packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 851961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi put(mcastv4packet, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr); 852f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen 853f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen ByteBuffer mcastv6packet = ByteBuffer.wrap(new byte[100]); 854f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen mcastv6packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6); 855f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_UDP); 856961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi put(mcastv6packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr); 857f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen 858f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen // Construct IPv4 broadcast packet. 859961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi ByteBuffer bcastv4packet1 = ByteBuffer.wrap(new byte[100]); 860961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi bcastv4packet1.put(ETH_BROADCAST_MAC_ADDRESS); 861961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi bcastv4packet1.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 862961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi put(bcastv4packet1, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr); 863961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi 864961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi ByteBuffer bcastv4packet2 = ByteBuffer.wrap(new byte[100]); 865961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi bcastv4packet2.put(ETH_BROADCAST_MAC_ADDRESS); 866961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi bcastv4packet2.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 867961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi put(bcastv4packet2, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS); 868961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi 869961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi // Construct IPv4 broadcast with L2 unicast address packet (b/30231088). 870961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi ByteBuffer bcastv4unicastl2packet = ByteBuffer.wrap(new byte[100]); 871961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi bcastv4unicastl2packet.put(TestApfFilter.MOCK_MAC_ADDR); 872961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi bcastv4unicastl2packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 873961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi put(bcastv4unicastl2packet, IPV4_DEST_ADDR_OFFSET, broadcastIpv4Addr); 87411e13e2175674389ed18c2b1e1af69c5ad931e8fLorenzo Colitti 8759132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Verify initially disabled multicast filter is off 876961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertPass(program, mcastv4packet.array()); 877961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertPass(program, mcastv6packet.array()); 878961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertPass(program, bcastv4packet1.array()); 879961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertPass(program, bcastv4packet2.array()); 880961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertPass(program, bcastv4unicastl2packet.array()); 8819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 8829132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Turn on multicast filter and verify it works 8839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen ipManagerCallback.resetApfProgramWait(); 8849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen apfFilter.setMulticastFilter(true); 8859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen program = ipManagerCallback.getApfProgram(); 886961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertDrop(program, mcastv4packet.array()); 887961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertDrop(program, mcastv6packet.array()); 888961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertDrop(program, bcastv4packet1.array()); 889961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertDrop(program, bcastv4packet2.array()); 8907d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi assertDrop(program, bcastv4unicastl2packet.array()); 8919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 8929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Turn off multicast filter and verify it's off 8939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen ipManagerCallback.resetApfProgramWait(); 8949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen apfFilter.setMulticastFilter(false); 8959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen program = ipManagerCallback.getApfProgram(); 896961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertPass(program, mcastv4packet.array()); 897961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertPass(program, mcastv6packet.array()); 898961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertPass(program, bcastv4packet1.array()); 899961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertPass(program, bcastv4packet2.array()); 900961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertPass(program, bcastv4unicastl2packet.array()); 9019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 9029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Verify it can be initialized to on 9039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen ipManagerCallback.resetApfProgramWait(); 9049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen apfFilter.shutdown(); 9054dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, 9064dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy DROP_802_3_FRAMES, mLog); 9077d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi apfFilter.setLinkProperties(lp); 9089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen program = ipManagerCallback.getApfProgram(); 909961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertDrop(program, mcastv4packet.array()); 910961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertDrop(program, mcastv6packet.array()); 911961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertDrop(program, bcastv4packet1.array()); 9127d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi assertDrop(program, bcastv4unicastl2packet.array()); 91311e13e2175674389ed18c2b1e1af69c5ad931e8fLorenzo Colitti 91411e13e2175674389ed18c2b1e1af69c5ad931e8fLorenzo Colitti // Verify that ICMPv6 multicast is not dropped. 915f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6); 916961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertPass(program, mcastv6packet.array()); 9179132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 9189132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen apfFilter.shutdown(); 9199132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 9209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 9214dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy @SmallTest 9224dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy public void testApfFilter802_3() throws Exception { 9234dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); 9244dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19); 9254dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy LinkProperties lp = new LinkProperties(); 9264dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy lp.addLinkAddress(link); 9274dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy 9284dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, 9294dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy ALLOW_802_3_FRAMES, mLog); 9304dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy apfFilter.setLinkProperties(lp); 9314dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy 9324dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy byte[] program = ipManagerCallback.getApfProgram(); 9334dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy 9344dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy // Verify empty packet of 100 zero bytes is passed 9354dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy // Note that eth-type = 0 makes it an IEEE802.3 frame 9364dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 9374dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy assertPass(program, packet.array()); 9384dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy 9394dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy // Verify empty packet with IPv4 is passed 9404dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 9414dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy assertPass(program, packet.array()); 9424dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy 9434dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy // Verify empty IPv6 packet is passed 9444dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6); 9454dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy assertPass(program, packet.array()); 9464dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy 9474dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy // Now turn on the filter 9484dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy ipManagerCallback.resetApfProgramWait(); 9494dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy apfFilter.shutdown(); 9504dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, 9514dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy DROP_802_3_FRAMES, mLog); 9524dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy apfFilter.setLinkProperties(lp); 9534dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy program = ipManagerCallback.getApfProgram(); 9544dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy 9554dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy // Verify that IEEE802.3 frame is dropped 9564dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy // In this case ethtype is used for payload length 9574dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy packet.putShort(ETH_ETHERTYPE_OFFSET, (short)(100 - 14)); 9584dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy assertDrop(program, packet.array()); 9594dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy 9604dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy // Verify that IPv4 (as example of Ethernet II) frame will pass 9614dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 9624dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy assertPass(program, packet.array()); 9634dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy 9644dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy // Verify that IPv6 (as example of Ethernet II) frame will pass 9654dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6); 9664dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy assertPass(program, packet.array()); 9674dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy 9684dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy apfFilter.shutdown(); 9694dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy } 9704dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy 97138db976514ff2ad12d207a927219762eab179882Hugo Benichi private byte[] getProgram(MockIpManagerCallback cb, ApfFilter filter, LinkProperties lp) { 97238db976514ff2ad12d207a927219762eab179882Hugo Benichi cb.resetApfProgramWait(); 97338db976514ff2ad12d207a927219762eab179882Hugo Benichi filter.setLinkProperties(lp); 97438db976514ff2ad12d207a927219762eab179882Hugo Benichi return cb.getApfProgram(); 97538db976514ff2ad12d207a927219762eab179882Hugo Benichi } 97638db976514ff2ad12d207a927219762eab179882Hugo Benichi 97738db976514ff2ad12d207a927219762eab179882Hugo Benichi private void verifyArpFilter(byte[] program, int filterResult) { 97838db976514ff2ad12d207a927219762eab179882Hugo Benichi // Verify ARP request packet 979961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertPass(program, arpRequestBroadcast(MOCK_IPV4_ADDR)); 980961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertVerdict(filterResult, program, arpRequestBroadcast(ANOTHER_IPV4_ADDR)); 981961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertDrop(program, arpRequestBroadcast(IPV4_ANY_HOST_ADDR)); 98238db976514ff2ad12d207a927219762eab179882Hugo Benichi 98338db976514ff2ad12d207a927219762eab179882Hugo Benichi // Verify unicast ARP reply packet is always accepted. 984961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertPass(program, arpReplyUnicast(MOCK_IPV4_ADDR)); 985961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertPass(program, arpReplyUnicast(ANOTHER_IPV4_ADDR)); 986961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertPass(program, arpReplyUnicast(IPV4_ANY_HOST_ADDR)); 98738db976514ff2ad12d207a927219762eab179882Hugo Benichi 98838db976514ff2ad12d207a927219762eab179882Hugo Benichi // Verify GARP reply packets are always filtered 989961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertDrop(program, garpReply()); 9909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 9919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 992cfcc1cb7bf9caae440bf7c2c93efb43c9f90aa73Hugo Benichi @SmallTest 9939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen public void testApfFilterArp() throws Exception { 9949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); 9954dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, 9964dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy DROP_802_3_FRAMES, mLog); 9979132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 99838db976514ff2ad12d207a927219762eab179882Hugo Benichi // Verify initially ARP request filter is off, and GARP filter is on. 99938db976514ff2ad12d207a927219762eab179882Hugo Benichi verifyArpFilter(ipManagerCallback.getApfProgram(), PASS); 10009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 10019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Inform ApfFilter of our address and verify ARP filtering is on 100238db976514ff2ad12d207a927219762eab179882Hugo Benichi LinkAddress linkAddress = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 24); 10039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen LinkProperties lp = new LinkProperties(); 100438db976514ff2ad12d207a927219762eab179882Hugo Benichi assertTrue(lp.addLinkAddress(linkAddress)); 100538db976514ff2ad12d207a927219762eab179882Hugo Benichi verifyArpFilter(getProgram(ipManagerCallback, apfFilter, lp), DROP); 10069132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 10079132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Inform ApfFilter of loss of IP and verify ARP filtering is off 100838db976514ff2ad12d207a927219762eab179882Hugo Benichi verifyArpFilter(getProgram(ipManagerCallback, apfFilter, new LinkProperties()), PASS); 10099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 10109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen apfFilter.shutdown(); 10119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 10129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 101338db976514ff2ad12d207a927219762eab179882Hugo Benichi private static byte[] arpRequestBroadcast(byte[] tip) { 101438db976514ff2ad12d207a927219762eab179882Hugo Benichi ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 101538db976514ff2ad12d207a927219762eab179882Hugo Benichi packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP); 1016961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS); 1017961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER); 1018961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip); 101938db976514ff2ad12d207a927219762eab179882Hugo Benichi return packet.array(); 102038db976514ff2ad12d207a927219762eab179882Hugo Benichi } 102138db976514ff2ad12d207a927219762eab179882Hugo Benichi 102238db976514ff2ad12d207a927219762eab179882Hugo Benichi private static byte[] arpReplyUnicast(byte[] tip) { 102338db976514ff2ad12d207a927219762eab179882Hugo Benichi ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 102438db976514ff2ad12d207a927219762eab179882Hugo Benichi packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP); 1025961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER); 1026961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip); 102738db976514ff2ad12d207a927219762eab179882Hugo Benichi return packet.array(); 102838db976514ff2ad12d207a927219762eab179882Hugo Benichi } 102938db976514ff2ad12d207a927219762eab179882Hugo Benichi 103038db976514ff2ad12d207a927219762eab179882Hugo Benichi private static byte[] garpReply() { 103138db976514ff2ad12d207a927219762eab179882Hugo Benichi ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 103238db976514ff2ad12d207a927219762eab179882Hugo Benichi packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP); 1033961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS); 1034961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER); 1035961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, IPV4_ANY_HOST_ADDR); 103638db976514ff2ad12d207a927219762eab179882Hugo Benichi return packet.array(); 103738db976514ff2ad12d207a927219762eab179882Hugo Benichi } 103838db976514ff2ad12d207a927219762eab179882Hugo Benichi 10399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Verify that the last program pushed to the IpManager.Callback properly filters the 10409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // given packet for the given lifetime. 10414456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi private void verifyRaLifetime(byte[] program, ByteBuffer packet, int lifetime) { 10424456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi final int FRACTION_OF_LIFETIME = 6; 10434456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi final int ageLimit = lifetime / FRACTION_OF_LIFETIME; 10449132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 10454456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi // Verify new program should drop RA for 1/6th its lifetime and pass afterwards. 1046961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertDrop(program, packet.array()); 10474456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi assertDrop(program, packet.array(), ageLimit); 10484456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi assertPass(program, packet.array(), ageLimit + 1); 10499132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen assertPass(program, packet.array(), lifetime); 10509132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Verify RA checksum is ignored 10514456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi final short originalChecksum = packet.getShort(ICMP6_RA_CHECKSUM_OFFSET); 10529132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)12345); 1053961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertDrop(program, packet.array()); 10549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)-12345); 1055961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertDrop(program, packet.array()); 10564456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, originalChecksum); 10579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 10589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Verify other changes to RA make it not match filter 10594456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi final byte originalFirstByte = packet.get(0); 10609132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen packet.put(0, (byte)-1); 1061961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertPass(program, packet.array()); 10629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen packet.put(0, (byte)0); 1063961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertDrop(program, packet.array()); 10644456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi packet.put(0, originalFirstByte); 10659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 10669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 10679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Test that when ApfFilter is shown the given packet, it generates a program to filter it 10689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // for the given lifetime. 10699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private void testRaLifetime(TestApfFilter apfFilter, MockIpManagerCallback ipManagerCallback, 10709132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen ByteBuffer packet, int lifetime) throws IOException, ErrnoException { 10719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Verify new program generated if ApfFilter witnesses RA 10729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen ipManagerCallback.resetApfProgramWait(); 10739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen apfFilter.pretendPacketReceived(packet.array()); 10744456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi byte[] program = ipManagerCallback.getApfProgram(); 10754456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi verifyRaLifetime(program, packet, lifetime); 10769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 10779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 10786ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi private void verifyRaEvent(RaEvent expected) { 10796ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi ArgumentCaptor<Parcelable> captor = ArgumentCaptor.forClass(Parcelable.class); 10806ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi verify(mLog, atLeastOnce()).log(captor.capture()); 10816ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi RaEvent got = lastRaEvent(captor.getAllValues()); 10826ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi if (!raEventEquals(expected, got)) { 10836ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi assertEquals(expected, got); // fail for printing an assertion error message. 10846ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi } 10856ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi } 10866ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi 10876ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi private RaEvent lastRaEvent(List<Parcelable> events) { 10886ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi RaEvent got = null; 10896ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi for (Parcelable ev : events) { 10906ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi if (ev instanceof RaEvent) { 10916ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi got = (RaEvent) ev; 10926ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi } 10936ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi } 10946ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi return got; 10956ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi } 10966ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi 10976ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi private boolean raEventEquals(RaEvent ev1, RaEvent ev2) { 10986ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi return (ev1 != null) && (ev2 != null) 10996ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi && (ev1.routerLifetime == ev2.routerLifetime) 11006ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi && (ev1.prefixValidLifetime == ev2.prefixValidLifetime) 11016ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi && (ev1.prefixPreferredLifetime == ev2.prefixPreferredLifetime) 11026ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi && (ev1.routeInfoLifetime == ev2.routeInfoLifetime) 11036ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi && (ev1.rdnssLifetime == ev2.rdnssLifetime) 11046ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi && (ev1.dnsslLifetime == ev2.dnsslLifetime); 11056ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi } 11066ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi 11078995d85b9432387520c9f04a69251536754b996bLorenzo Colitti private void assertInvalidRa(TestApfFilter apfFilter, MockIpManagerCallback ipManagerCallback, 11088995d85b9432387520c9f04a69251536754b996bLorenzo Colitti ByteBuffer packet) throws IOException, ErrnoException { 11098995d85b9432387520c9f04a69251536754b996bLorenzo Colitti ipManagerCallback.resetApfProgramWait(); 11108995d85b9432387520c9f04a69251536754b996bLorenzo Colitti apfFilter.pretendPacketReceived(packet.array()); 11118995d85b9432387520c9f04a69251536754b996bLorenzo Colitti ipManagerCallback.assertNoProgramUpdate(); 11128995d85b9432387520c9f04a69251536754b996bLorenzo Colitti } 11138995d85b9432387520c9f04a69251536754b996bLorenzo Colitti 1114cfcc1cb7bf9caae440bf7c2c93efb43c9f90aa73Hugo Benichi @SmallTest 11159132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen public void testApfFilterRa() throws Exception { 11169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); 11174dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy TestApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, 11184dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy DROP_802_3_FRAMES, mLog); 11199132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen byte[] program = ipManagerCallback.getApfProgram(); 11209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 11214456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi final int ROUTER_LIFETIME = 1000; 11224456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi final int PREFIX_VALID_LIFETIME = 200; 11234456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi final int PREFIX_PREFERRED_LIFETIME = 100; 11244456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi final int RDNSS_LIFETIME = 300; 11254456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi final int ROUTE_LIFETIME = 400; 11264456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi // Note that lifetime of 2000 will be ignored in favor of shorter route lifetime of 1000. 11274456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi final int DNSSL_LIFETIME = 2000; 1128967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz final int VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET = ETH_HEADER_LEN; 1129967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz // IPv6, traffic class = 0, flow label = 0x12345 1130967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz final int VERSION_TRAFFIC_CLASS_FLOW_LABEL = 0x60012345; 11314456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi 11329132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Verify RA is passed the first time 11339132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen ByteBuffer basePacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]); 11349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen basePacket.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6); 1135967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz basePacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET, 1136967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz VERSION_TRAFFIC_CLASS_FLOW_LABEL); 11379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen basePacket.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6); 11389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen basePacket.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_ADVERTISEMENT); 11394456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi basePacket.putShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET, (short)ROUTER_LIFETIME); 114011e13e2175674389ed18c2b1e1af69c5ad931e8fLorenzo Colitti basePacket.position(IPV6_DEST_ADDR_OFFSET); 114111e13e2175674389ed18c2b1e1af69c5ad931e8fLorenzo Colitti basePacket.put(IPV6_ALL_NODES_ADDRESS); 1142961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi assertPass(program, basePacket.array()); 11439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 11444456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi testRaLifetime(apfFilter, ipManagerCallback, basePacket, ROUTER_LIFETIME); 11454456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, -1)); 11469132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 1147967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz ByteBuffer newFlowLabelPacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]); 1148967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz basePacket.clear(); 1149967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz newFlowLabelPacket.put(basePacket); 1150967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz // Check that changes are ignored in every byte of the flow label. 1151967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz newFlowLabelPacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET, 1152967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz VERSION_TRAFFIC_CLASS_FLOW_LABEL + 0x11111); 1153967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz 11548995d85b9432387520c9f04a69251536754b996bLorenzo Colitti // Ensure zero-length options cause the packet to be silently skipped. 11558995d85b9432387520c9f04a69251536754b996bLorenzo Colitti // Do this before we test other packets. http://b/29586253 11568995d85b9432387520c9f04a69251536754b996bLorenzo Colitti ByteBuffer zeroLengthOptionPacket = ByteBuffer.wrap( 11578995d85b9432387520c9f04a69251536754b996bLorenzo Colitti new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]); 11588995d85b9432387520c9f04a69251536754b996bLorenzo Colitti basePacket.clear(); 11598995d85b9432387520c9f04a69251536754b996bLorenzo Colitti zeroLengthOptionPacket.put(basePacket); 11608995d85b9432387520c9f04a69251536754b996bLorenzo Colitti zeroLengthOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE); 11618995d85b9432387520c9f04a69251536754b996bLorenzo Colitti zeroLengthOptionPacket.put((byte)0); 11628995d85b9432387520c9f04a69251536754b996bLorenzo Colitti assertInvalidRa(apfFilter, ipManagerCallback, zeroLengthOptionPacket); 11638995d85b9432387520c9f04a69251536754b996bLorenzo Colitti 11649132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Generate several RAs with different options and lifetimes, and verify when 11659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // ApfFilter is shown these packets, it generates programs to filter them for the 11669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // appropriate lifetime. 11679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen ByteBuffer prefixOptionPacket = ByteBuffer.wrap( 11689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_LEN]); 11699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen basePacket.clear(); 11709132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen prefixOptionPacket.put(basePacket); 11719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen prefixOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE); 11729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen prefixOptionPacket.put((byte)(ICMP6_PREFIX_OPTION_LEN / 8)); 11739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen prefixOptionPacket.putInt( 11744456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET, 11754456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi PREFIX_PREFERRED_LIFETIME); 11769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen prefixOptionPacket.putInt( 11774456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET, 11784456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi PREFIX_VALID_LIFETIME); 11794456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi testRaLifetime(apfFilter, ipManagerCallback, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME); 11804456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi verifyRaEvent(new RaEvent( 11814456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi ROUTER_LIFETIME, PREFIX_VALID_LIFETIME, PREFIX_PREFERRED_LIFETIME, -1, -1, -1)); 11829132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 11839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen ByteBuffer rdnssOptionPacket = ByteBuffer.wrap( 11849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]); 11859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen basePacket.clear(); 11869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen rdnssOptionPacket.put(basePacket); 11879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen rdnssOptionPacket.put((byte)ICMP6_RDNSS_OPTION_TYPE); 11889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen rdnssOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8)); 11899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen rdnssOptionPacket.putInt( 11904456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, RDNSS_LIFETIME); 11914456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi testRaLifetime(apfFilter, ipManagerCallback, rdnssOptionPacket, RDNSS_LIFETIME); 11924456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, RDNSS_LIFETIME, -1)); 11939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 11949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen ByteBuffer routeInfoOptionPacket = ByteBuffer.wrap( 11959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]); 11969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen basePacket.clear(); 11979132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen routeInfoOptionPacket.put(basePacket); 11989132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen routeInfoOptionPacket.put((byte)ICMP6_ROUTE_INFO_OPTION_TYPE); 11999132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen routeInfoOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8)); 12009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen routeInfoOptionPacket.putInt( 12014456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, ROUTE_LIFETIME); 12024456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi testRaLifetime(apfFilter, ipManagerCallback, routeInfoOptionPacket, ROUTE_LIFETIME); 12034456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, ROUTE_LIFETIME, -1, -1)); 12049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 12059132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen ByteBuffer dnsslOptionPacket = ByteBuffer.wrap( 12069132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]); 12079132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen basePacket.clear(); 12089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen dnsslOptionPacket.put(basePacket); 12099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen dnsslOptionPacket.put((byte)ICMP6_DNSSL_OPTION_TYPE); 12109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen dnsslOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8)); 12119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen dnsslOptionPacket.putInt( 12124456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, DNSSL_LIFETIME); 12134456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi testRaLifetime(apfFilter, ipManagerCallback, dnsslOptionPacket, ROUTER_LIFETIME); 12144456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, DNSSL_LIFETIME)); 12159132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 12169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen // Verify that current program filters all five RAs: 12174456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi program = ipManagerCallback.getApfProgram(); 12184456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi verifyRaLifetime(program, basePacket, ROUTER_LIFETIME); 1219967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz verifyRaLifetime(program, newFlowLabelPacket, ROUTER_LIFETIME); 12204456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi verifyRaLifetime(program, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME); 12214456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi verifyRaLifetime(program, rdnssOptionPacket, RDNSS_LIFETIME); 12224456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi verifyRaLifetime(program, routeInfoOptionPacket, ROUTE_LIFETIME); 12234456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi verifyRaLifetime(program, dnsslOptionPacket, ROUTER_LIFETIME); 12249132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 12259132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen apfFilter.shutdown(); 12269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 12279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 12289132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen /** 12299132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * Stage a file for testing, i.e. make it native accessible. Given a resource ID, 12309132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * copy that resource into the app's data directory and return the path to it. 12319132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen */ 12329132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private String stageFile(int rawId) throws Exception { 12339132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen File file = new File(getContext().getFilesDir(), "staged_file"); 12349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen new File(file.getParent()).mkdirs(); 12359132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen InputStream in = null; 12369132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen OutputStream out = null; 12379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen try { 12389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen in = getContext().getResources().openRawResource(rawId); 12399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen out = new FileOutputStream(file); 12409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen Streams.copy(in, out); 12419132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } finally { 12429132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen if (in != null) in.close(); 12439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen if (out != null) out.close(); 12449132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 12459132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen return file.getAbsolutePath(); 12469132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen } 12479132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 1248961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi private static void put(ByteBuffer buffer, int position, byte[] bytes) { 1249961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi final int original = buffer.position(); 1250961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi buffer.position(position); 1251961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi buffer.put(bytes); 1252961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi buffer.position(original); 1253961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi } 1254961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi 12555d2654124e9e77dbda102a4435595c552cbc8e36Hugo Benichi @SmallTest 12560668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi public void testRaParsing() throws Exception { 12570668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi final int maxRandomPacketSize = 512; 12580668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi final Random r = new Random(); 12590668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi MockIpManagerCallback cb = new MockIpManagerCallback(); 12604dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST, 12614dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy DROP_802_3_FRAMES, mLog); 12620668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi for (int i = 0; i < 1000; i++) { 12630668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)]; 12640668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi r.nextBytes(packet); 12650668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi try { 12660668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi apfFilter.new Ra(packet, packet.length); 12670668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi } catch (ApfFilter.InvalidRaException e) { 12680668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi } catch (Exception e) { 12690668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi throw new Exception("bad packet: " + HexDump.toHexString(packet), e); 12700668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi } 12710668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi } 12720668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi } 12730668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi 12745d2654124e9e77dbda102a4435595c552cbc8e36Hugo Benichi @SmallTest 12750668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi public void testRaProcessing() throws Exception { 12760668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi final int maxRandomPacketSize = 512; 12770668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi final Random r = new Random(); 12780668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi MockIpManagerCallback cb = new MockIpManagerCallback(); 12794dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST, 12804dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy DROP_802_3_FRAMES, mLog); 12810668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi for (int i = 0; i < 1000; i++) { 12820668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)]; 12830668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi r.nextBytes(packet); 12840668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi try { 12850668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi apfFilter.processRa(packet, packet.length); 12860668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi } catch (Exception e) { 12870668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi throw new Exception("bad packet: " + HexDump.toHexString(packet), e); 12880668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi } 12890668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi } 12900668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi } 12910668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi 12929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen /** 12939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * Call the APF interpreter the run {@code program} on {@code packet} pretending the 12949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * filter was installed {@code filter_age} seconds ago. 12959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen */ 12969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private native static int apfSimulate(byte[] program, byte[] packet, int filter_age); 12979132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 12989132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen /** 12999132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * Compile a tcpdump human-readable filter (e.g. "icmp" or "tcp port 54") into a BPF 13009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * prorgam and return a human-readable dump of the BPF program identical to "tcpdump -d". 13019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen */ 13029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private native static String compileToBpf(String filter); 13039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen 13049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen /** 13059132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * Open packet capture file {@code pcap_filename} and filter the packets using tcpdump 13069132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * human-readable filter (e.g. "icmp" or "tcp port 54") compiled to a BPF program and 13079132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * at the same time using APF program {@code apf_program}. Return {@code true} if 13089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * both APF and BPF programs filter out exactly the same packets. 13099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen */ 13109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen private native static boolean compareBpfApf(String filter, String pcap_filename, 13119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen byte[] apf_program); 13127d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi 13135d2654124e9e77dbda102a4435595c552cbc8e36Hugo Benichi @SmallTest 13147d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi public void testBroadcastAddress() throws Exception { 13157d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 0)); 13167d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi assertEqualsIp("0.0.0.0", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 32)); 13177d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi assertEqualsIp("0.0.3.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 22)); 13187d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi assertEqualsIp("0.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 8)); 13197d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi 13207d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 0)); 13217d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi assertEqualsIp("10.0.0.1", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 32)); 13227d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi assertEqualsIp("10.0.0.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 24)); 13237d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi assertEqualsIp("10.0.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 16)); 13247d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi } 13257d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi 13267d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi public void assertEqualsIp(String expected, int got) throws Exception { 1327495a17b332e57ea4c0162a4ae63d820b947e3719Hugo Benichi int want = bytesToBEInt(InetAddress.getByName(expected).getAddress()); 13287d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi assertEquals(want, got); 13297d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi } 13309132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen} 1331