Home | History | Annotate | Download | only in apf
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.net.apf;
     18 
     19 import static android.net.util.NetworkConstants.*;
     20 import static android.system.OsConstants.*;
     21 import static com.android.internal.util.BitUtils.bytesToBEInt;
     22 import static com.android.internal.util.BitUtils.put;
     23 import static org.junit.Assert.assertEquals;
     24 import static org.junit.Assert.assertFalse;
     25 import static org.junit.Assert.assertTrue;
     26 import static org.junit.Assert.fail;
     27 import static org.mockito.Mockito.atLeastOnce;
     28 import static org.mockito.Mockito.verify;
     29 
     30 import android.content.Context;
     31 import android.net.LinkAddress;
     32 import android.net.LinkProperties;
     33 import android.net.apf.ApfFilter.ApfConfiguration;
     34 import android.net.apf.ApfGenerator.IllegalInstructionException;
     35 import android.net.apf.ApfGenerator.Register;
     36 import android.net.ip.IpClient;
     37 import android.net.metrics.IpConnectivityLog;
     38 import android.net.metrics.RaEvent;
     39 import android.net.util.InterfaceParams;
     40 import android.os.ConditionVariable;
     41 import android.os.Parcelable;
     42 import android.os.SystemClock;
     43 import android.support.test.InstrumentationRegistry;
     44 import android.support.test.filters.SmallTest;
     45 import android.support.test.runner.AndroidJUnit4;
     46 import android.system.ErrnoException;
     47 import android.system.Os;
     48 import android.text.format.DateUtils;
     49 import com.android.frameworks.tests.net.R;
     50 import com.android.internal.util.HexDump;
     51 import java.io.File;
     52 import java.io.FileDescriptor;
     53 import java.io.FileOutputStream;
     54 import java.io.IOException;
     55 import java.io.InputStream;
     56 import java.io.OutputStream;
     57 import java.net.InetAddress;
     58 import java.nio.ByteBuffer;
     59 import java.util.List;
     60 import java.util.Random;
     61 import libcore.io.IoUtils;
     62 import libcore.io.Streams;
     63 import org.junit.Before;
     64 import org.junit.Test;
     65 import org.junit.runner.RunWith;
     66 import org.mockito.ArgumentCaptor;
     67 import org.mockito.Mock;
     68 import org.mockito.MockitoAnnotations;
     69 
     70 /**
     71  * Tests for APF program generator and interpreter.
     72  *
     73  * Build, install and run with:
     74  *  runtest frameworks-net -c android.net.apf.ApfTest
     75  */
     76 @RunWith(AndroidJUnit4.class)
     77 @SmallTest
     78 public class ApfTest {
     79     private static final int TIMEOUT_MS = 500;
     80     private final static int MIN_APF_VERSION = 2;
     81 
     82     @Mock IpConnectivityLog mLog;
     83     @Mock Context mContext;
     84 
     85     @Before
     86     public void setUp() throws Exception {
     87         MockitoAnnotations.initMocks(this);
     88         // Load up native shared library containing APF interpreter exposed via JNI.
     89         System.loadLibrary("frameworksnettestsjni");
     90     }
     91 
     92     // Expected return codes from APF interpreter.
     93     private final static int PASS = 1;
     94     private final static int DROP = 0;
     95     // Interpreter will just accept packets without link layer headers, so pad fake packet to at
     96     // least the minimum packet size.
     97     private final static int MIN_PKT_SIZE = 15;
     98 
     99     private static final ApfCapabilities MOCK_APF_CAPABILITIES =
    100       new ApfCapabilities(2, 1700, ARPHRD_ETHER);
    101 
    102     private final static boolean DROP_MULTICAST = true;
    103     private final static boolean ALLOW_MULTICAST = false;
    104 
    105     private final static boolean DROP_802_3_FRAMES = true;
    106     private final static boolean ALLOW_802_3_FRAMES = false;
    107 
    108     private static ApfConfiguration getDefaultConfig() {
    109         ApfFilter.ApfConfiguration config = new ApfConfiguration();
    110         config.apfCapabilities = MOCK_APF_CAPABILITIES;
    111         config.multicastFilter = ALLOW_MULTICAST;
    112         config.ieee802_3Filter = ALLOW_802_3_FRAMES;
    113         config.ethTypeBlackList = new int[0];
    114         return config;
    115     }
    116 
    117     private static String label(int code) {
    118         switch (code) {
    119             case PASS: return "PASS";
    120             case DROP: return "DROP";
    121             default:   return "UNKNOWN";
    122         }
    123     }
    124 
    125     private static void assertReturnCodesEqual(int expected, int got) {
    126         assertEquals(label(expected), label(got));
    127     }
    128 
    129     private void assertVerdict(int expected, byte[] program, byte[] packet, int filterAge) {
    130         assertReturnCodesEqual(expected, apfSimulate(program, packet, null, filterAge));
    131     }
    132 
    133     private void assertVerdict(int expected, byte[] program, byte[] packet) {
    134         assertReturnCodesEqual(expected, apfSimulate(program, packet, null, 0));
    135     }
    136 
    137     private void assertPass(byte[] program, byte[] packet, int filterAge) {
    138         assertVerdict(PASS, program, packet, filterAge);
    139     }
    140 
    141     private void assertPass(byte[] program, byte[] packet) {
    142         assertVerdict(PASS, program, packet);
    143     }
    144 
    145     private void assertDrop(byte[] program, byte[] packet, int filterAge) {
    146         assertVerdict(DROP, program, packet, filterAge);
    147     }
    148 
    149     private void assertDrop(byte[] program, byte[] packet) {
    150         assertVerdict(DROP, program, packet);
    151     }
    152 
    153     private void assertProgramEquals(byte[] expected, byte[] program) throws AssertionError {
    154         // assertArrayEquals() would only print one byte, making debugging difficult.
    155         if (!java.util.Arrays.equals(expected, program)) {
    156             throw new AssertionError(
    157                     "\nexpected: " + HexDump.toHexString(expected) +
    158                     "\nactual:   " + HexDump.toHexString(program));
    159         }
    160     }
    161 
    162     private void assertDataMemoryContents(
    163             int expected, byte[] program, byte[] packet, byte[] data, byte[] expected_data)
    164             throws IllegalInstructionException, Exception {
    165         assertReturnCodesEqual(expected, apfSimulate(program, packet, data, 0 /* filterAge */));
    166 
    167         // assertArrayEquals() would only print one byte, making debugging difficult.
    168         if (!java.util.Arrays.equals(expected_data, data)) {
    169             throw new Exception(
    170                     "\nprogram:     " + HexDump.toHexString(program) +
    171                     "\ndata memory: " + HexDump.toHexString(data) +
    172                     "\nexpected:    " + HexDump.toHexString(expected_data));
    173         }
    174     }
    175 
    176     private void assertVerdict(int expected, ApfGenerator gen, byte[] packet, int filterAge)
    177             throws IllegalInstructionException {
    178         assertReturnCodesEqual(expected, apfSimulate(gen.generate(), packet, null,
    179               filterAge));
    180     }
    181 
    182     private void assertPass(ApfGenerator gen, byte[] packet, int filterAge)
    183             throws IllegalInstructionException {
    184         assertVerdict(PASS, gen, packet, filterAge);
    185     }
    186 
    187     private void assertDrop(ApfGenerator gen, byte[] packet, int filterAge)
    188             throws IllegalInstructionException {
    189         assertVerdict(DROP, gen, packet, filterAge);
    190     }
    191 
    192     private void assertPass(ApfGenerator gen)
    193             throws IllegalInstructionException {
    194         assertVerdict(PASS, gen, new byte[MIN_PKT_SIZE], 0);
    195     }
    196 
    197     private void assertDrop(ApfGenerator gen)
    198             throws IllegalInstructionException {
    199         assertVerdict(DROP, gen, new byte[MIN_PKT_SIZE], 0);
    200     }
    201 
    202     /**
    203      * Test each instruction by generating a program containing the instruction,
    204      * generating bytecode for that program and running it through the
    205      * interpreter to verify it functions correctly.
    206      */
    207     @Test
    208     public void testApfInstructions() throws IllegalInstructionException {
    209         // Empty program should pass because having the program counter reach the
    210         // location immediately after the program indicates the packet should be
    211         // passed to the AP.
    212         ApfGenerator gen = new ApfGenerator(MIN_APF_VERSION);
    213         assertPass(gen);
    214 
    215         // Test jumping to pass label.
    216         gen = new ApfGenerator(MIN_APF_VERSION);
    217         gen.addJump(gen.PASS_LABEL);
    218         byte[] program = gen.generate();
    219         assertEquals(1, program.length);
    220         assertEquals((14 << 3) | (0 << 1) | 0, program[0]);
    221         assertPass(program, new byte[MIN_PKT_SIZE], 0);
    222 
    223         // Test jumping to drop label.
    224         gen = new ApfGenerator(MIN_APF_VERSION);
    225         gen.addJump(gen.DROP_LABEL);
    226         program = gen.generate();
    227         assertEquals(2, program.length);
    228         assertEquals((14 << 3) | (1 << 1) | 0, program[0]);
    229         assertEquals(1, program[1]);
    230         assertDrop(program, new byte[15], 15);
    231 
    232         // Test jumping if equal to 0.
    233         gen = new ApfGenerator(MIN_APF_VERSION);
    234         gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
    235         assertDrop(gen);
    236 
    237         // Test jumping if not equal to 0.
    238         gen = new ApfGenerator(MIN_APF_VERSION);
    239         gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL);
    240         assertPass(gen);
    241         gen = new ApfGenerator(MIN_APF_VERSION);
    242         gen.addLoadImmediate(Register.R0, 1);
    243         gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL);
    244         assertDrop(gen);
    245 
    246         // Test jumping if registers equal.
    247         gen = new ApfGenerator(MIN_APF_VERSION);
    248         gen.addJumpIfR0EqualsR1(gen.DROP_LABEL);
    249         assertDrop(gen);
    250 
    251         // Test jumping if registers not equal.
    252         gen = new ApfGenerator(MIN_APF_VERSION);
    253         gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL);
    254         assertPass(gen);
    255         gen = new ApfGenerator(MIN_APF_VERSION);
    256         gen.addLoadImmediate(Register.R0, 1);
    257         gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL);
    258         assertDrop(gen);
    259 
    260         // Test load immediate.
    261         gen = new ApfGenerator(MIN_APF_VERSION);
    262         gen.addLoadImmediate(Register.R0, 1234567890);
    263         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
    264         assertDrop(gen);
    265 
    266         // Test add.
    267         gen = new ApfGenerator(MIN_APF_VERSION);
    268         gen.addAdd(1234567890);
    269         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
    270         assertDrop(gen);
    271 
    272         // Test subtract.
    273         gen = new ApfGenerator(MIN_APF_VERSION);
    274         gen.addAdd(-1234567890);
    275         gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
    276         assertDrop(gen);
    277 
    278         // Test or.
    279         gen = new ApfGenerator(MIN_APF_VERSION);
    280         gen.addOr(1234567890);
    281         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
    282         assertDrop(gen);
    283 
    284         // Test and.
    285         gen = new ApfGenerator(MIN_APF_VERSION);
    286         gen.addLoadImmediate(Register.R0, 1234567890);
    287         gen.addAnd(123456789);
    288         gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL);
    289         assertDrop(gen);
    290 
    291         // Test left shift.
    292         gen = new ApfGenerator(MIN_APF_VERSION);
    293         gen.addLoadImmediate(Register.R0, 1234567890);
    294         gen.addLeftShift(1);
    295         gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL);
    296         assertDrop(gen);
    297 
    298         // Test right shift.
    299         gen = new ApfGenerator(MIN_APF_VERSION);
    300         gen.addLoadImmediate(Register.R0, 1234567890);
    301         gen.addRightShift(1);
    302         gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL);
    303         assertDrop(gen);
    304 
    305         // Test multiply.
    306         gen = new ApfGenerator(MIN_APF_VERSION);
    307         gen.addLoadImmediate(Register.R0, 1234567890);
    308         gen.addMul(2);
    309         gen.addJumpIfR0Equals(1234567890 * 2, gen.DROP_LABEL);
    310         assertDrop(gen);
    311 
    312         // Test divide.
    313         gen = new ApfGenerator(MIN_APF_VERSION);
    314         gen.addLoadImmediate(Register.R0, 1234567890);
    315         gen.addDiv(2);
    316         gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL);
    317         assertDrop(gen);
    318 
    319         // Test divide by zero.
    320         gen = new ApfGenerator(MIN_APF_VERSION);
    321         gen.addDiv(0);
    322         gen.addJump(gen.DROP_LABEL);
    323         assertPass(gen);
    324 
    325         // Test add.
    326         gen = new ApfGenerator(MIN_APF_VERSION);
    327         gen.addLoadImmediate(Register.R1, 1234567890);
    328         gen.addAddR1();
    329         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
    330         assertDrop(gen);
    331 
    332         // Test subtract.
    333         gen = new ApfGenerator(MIN_APF_VERSION);
    334         gen.addLoadImmediate(Register.R1, -1234567890);
    335         gen.addAddR1();
    336         gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
    337         assertDrop(gen);
    338 
    339         // Test or.
    340         gen = new ApfGenerator(MIN_APF_VERSION);
    341         gen.addLoadImmediate(Register.R1, 1234567890);
    342         gen.addOrR1();
    343         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
    344         assertDrop(gen);
    345 
    346         // Test and.
    347         gen = new ApfGenerator(MIN_APF_VERSION);
    348         gen.addLoadImmediate(Register.R0, 1234567890);
    349         gen.addLoadImmediate(Register.R1, 123456789);
    350         gen.addAndR1();
    351         gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL);
    352         assertDrop(gen);
    353 
    354         // Test left shift.
    355         gen = new ApfGenerator(MIN_APF_VERSION);
    356         gen.addLoadImmediate(Register.R0, 1234567890);
    357         gen.addLoadImmediate(Register.R1, 1);
    358         gen.addLeftShiftR1();
    359         gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL);
    360         assertDrop(gen);
    361 
    362         // Test right shift.
    363         gen = new ApfGenerator(MIN_APF_VERSION);
    364         gen.addLoadImmediate(Register.R0, 1234567890);
    365         gen.addLoadImmediate(Register.R1, -1);
    366         gen.addLeftShiftR1();
    367         gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL);
    368         assertDrop(gen);
    369 
    370         // Test multiply.
    371         gen = new ApfGenerator(MIN_APF_VERSION);
    372         gen.addLoadImmediate(Register.R0, 1234567890);
    373         gen.addLoadImmediate(Register.R1, 2);
    374         gen.addMulR1();
    375         gen.addJumpIfR0Equals(1234567890 * 2, gen.DROP_LABEL);
    376         assertDrop(gen);
    377 
    378         // Test divide.
    379         gen = new ApfGenerator(MIN_APF_VERSION);
    380         gen.addLoadImmediate(Register.R0, 1234567890);
    381         gen.addLoadImmediate(Register.R1, 2);
    382         gen.addDivR1();
    383         gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL);
    384         assertDrop(gen);
    385 
    386         // Test divide by zero.
    387         gen = new ApfGenerator(MIN_APF_VERSION);
    388         gen.addDivR1();
    389         gen.addJump(gen.DROP_LABEL);
    390         assertPass(gen);
    391 
    392         // Test byte load.
    393         gen = new ApfGenerator(MIN_APF_VERSION);
    394         gen.addLoad8(Register.R0, 1);
    395         gen.addJumpIfR0Equals(45, gen.DROP_LABEL);
    396         assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
    397 
    398         // Test out of bounds load.
    399         gen = new ApfGenerator(MIN_APF_VERSION);
    400         gen.addLoad8(Register.R0, 16);
    401         gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
    402         assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
    403 
    404         // Test half-word load.
    405         gen = new ApfGenerator(MIN_APF_VERSION);
    406         gen.addLoad16(Register.R0, 1);
    407         gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL);
    408         assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
    409 
    410         // Test word load.
    411         gen = new ApfGenerator(MIN_APF_VERSION);
    412         gen.addLoad32(Register.R0, 1);
    413         gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL);
    414         assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0);
    415 
    416         // Test byte indexed load.
    417         gen = new ApfGenerator(MIN_APF_VERSION);
    418         gen.addLoadImmediate(Register.R1, 1);
    419         gen.addLoad8Indexed(Register.R0, 0);
    420         gen.addJumpIfR0Equals(45, gen.DROP_LABEL);
    421         assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
    422 
    423         // Test out of bounds indexed load.
    424         gen = new ApfGenerator(MIN_APF_VERSION);
    425         gen.addLoadImmediate(Register.R1, 8);
    426         gen.addLoad8Indexed(Register.R0, 8);
    427         gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
    428         assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
    429 
    430         // Test half-word indexed load.
    431         gen = new ApfGenerator(MIN_APF_VERSION);
    432         gen.addLoadImmediate(Register.R1, 1);
    433         gen.addLoad16Indexed(Register.R0, 0);
    434         gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL);
    435         assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
    436 
    437         // Test word indexed load.
    438         gen = new ApfGenerator(MIN_APF_VERSION);
    439         gen.addLoadImmediate(Register.R1, 1);
    440         gen.addLoad32Indexed(Register.R0, 0);
    441         gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL);
    442         assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0);
    443 
    444         // Test jumping if greater than.
    445         gen = new ApfGenerator(MIN_APF_VERSION);
    446         gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL);
    447         assertPass(gen);
    448         gen = new ApfGenerator(MIN_APF_VERSION);
    449         gen.addLoadImmediate(Register.R0, 1);
    450         gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL);
    451         assertDrop(gen);
    452 
    453         // Test jumping if less than.
    454         gen = new ApfGenerator(MIN_APF_VERSION);
    455         gen.addJumpIfR0LessThan(0, gen.DROP_LABEL);
    456         assertPass(gen);
    457         gen = new ApfGenerator(MIN_APF_VERSION);
    458         gen.addJumpIfR0LessThan(1, gen.DROP_LABEL);
    459         assertDrop(gen);
    460 
    461         // Test jumping if any bits set.
    462         gen = new ApfGenerator(MIN_APF_VERSION);
    463         gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
    464         assertPass(gen);
    465         gen = new ApfGenerator(MIN_APF_VERSION);
    466         gen.addLoadImmediate(Register.R0, 1);
    467         gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
    468         assertDrop(gen);
    469         gen = new ApfGenerator(MIN_APF_VERSION);
    470         gen.addLoadImmediate(Register.R0, 3);
    471         gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
    472         assertDrop(gen);
    473 
    474         // Test jumping if register greater than.
    475         gen = new ApfGenerator(MIN_APF_VERSION);
    476         gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL);
    477         assertPass(gen);
    478         gen = new ApfGenerator(MIN_APF_VERSION);
    479         gen.addLoadImmediate(Register.R0, 2);
    480         gen.addLoadImmediate(Register.R1, 1);
    481         gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL);
    482         assertDrop(gen);
    483 
    484         // Test jumping if register less than.
    485         gen = new ApfGenerator(MIN_APF_VERSION);
    486         gen.addJumpIfR0LessThanR1(gen.DROP_LABEL);
    487         assertPass(gen);
    488         gen = new ApfGenerator(MIN_APF_VERSION);
    489         gen.addLoadImmediate(Register.R1, 1);
    490         gen.addJumpIfR0LessThanR1(gen.DROP_LABEL);
    491         assertDrop(gen);
    492 
    493         // Test jumping if any bits set in register.
    494         gen = new ApfGenerator(MIN_APF_VERSION);
    495         gen.addLoadImmediate(Register.R1, 3);
    496         gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
    497         assertPass(gen);
    498         gen = new ApfGenerator(MIN_APF_VERSION);
    499         gen.addLoadImmediate(Register.R1, 3);
    500         gen.addLoadImmediate(Register.R0, 1);
    501         gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
    502         assertDrop(gen);
    503         gen = new ApfGenerator(MIN_APF_VERSION);
    504         gen.addLoadImmediate(Register.R1, 3);
    505         gen.addLoadImmediate(Register.R0, 3);
    506         gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
    507         assertDrop(gen);
    508 
    509         // Test load from memory.
    510         gen = new ApfGenerator(MIN_APF_VERSION);
    511         gen.addLoadFromMemory(Register.R0, 0);
    512         gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
    513         assertDrop(gen);
    514 
    515         // Test store to memory.
    516         gen = new ApfGenerator(MIN_APF_VERSION);
    517         gen.addLoadImmediate(Register.R1, 1234567890);
    518         gen.addStoreToMemory(Register.R1, 12);
    519         gen.addLoadFromMemory(Register.R0, 12);
    520         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
    521         assertDrop(gen);
    522 
    523         // Test filter age pre-filled memory.
    524         gen = new ApfGenerator(MIN_APF_VERSION);
    525         gen.addLoadFromMemory(Register.R0, gen.FILTER_AGE_MEMORY_SLOT);
    526         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
    527         assertDrop(gen, new byte[MIN_PKT_SIZE], 1234567890);
    528 
    529         // Test packet size pre-filled memory.
    530         gen = new ApfGenerator(MIN_APF_VERSION);
    531         gen.addLoadFromMemory(Register.R0, gen.PACKET_SIZE_MEMORY_SLOT);
    532         gen.addJumpIfR0Equals(MIN_PKT_SIZE, gen.DROP_LABEL);
    533         assertDrop(gen);
    534 
    535         // Test IPv4 header size pre-filled memory.
    536         gen = new ApfGenerator(MIN_APF_VERSION);
    537         gen.addLoadFromMemory(Register.R0, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
    538         gen.addJumpIfR0Equals(20, gen.DROP_LABEL);
    539         assertDrop(gen, new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x45}, 0);
    540 
    541         // Test not.
    542         gen = new ApfGenerator(MIN_APF_VERSION);
    543         gen.addLoadImmediate(Register.R0, 1234567890);
    544         gen.addNot(Register.R0);
    545         gen.addJumpIfR0Equals(~1234567890, gen.DROP_LABEL);
    546         assertDrop(gen);
    547 
    548         // Test negate.
    549         gen = new ApfGenerator(MIN_APF_VERSION);
    550         gen.addLoadImmediate(Register.R0, 1234567890);
    551         gen.addNeg(Register.R0);
    552         gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
    553         assertDrop(gen);
    554 
    555         // Test move.
    556         gen = new ApfGenerator(MIN_APF_VERSION);
    557         gen.addLoadImmediate(Register.R1, 1234567890);
    558         gen.addMove(Register.R0);
    559         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
    560         assertDrop(gen);
    561         gen = new ApfGenerator(MIN_APF_VERSION);
    562         gen.addLoadImmediate(Register.R0, 1234567890);
    563         gen.addMove(Register.R1);
    564         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
    565         assertDrop(gen);
    566 
    567         // Test swap.
    568         gen = new ApfGenerator(MIN_APF_VERSION);
    569         gen.addLoadImmediate(Register.R1, 1234567890);
    570         gen.addSwap();
    571         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
    572         assertDrop(gen);
    573         gen = new ApfGenerator(MIN_APF_VERSION);
    574         gen.addLoadImmediate(Register.R0, 1234567890);
    575         gen.addSwap();
    576         gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
    577         assertDrop(gen);
    578 
    579         // Test jump if bytes not equal.
    580         gen = new ApfGenerator(MIN_APF_VERSION);
    581         gen.addLoadImmediate(Register.R0, 1);
    582         gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
    583         program = gen.generate();
    584         assertEquals(6, program.length);
    585         assertEquals((13 << 3) | (1 << 1) | 0, program[0]);
    586         assertEquals(1, program[1]);
    587         assertEquals(((20 << 3) | (1 << 1) | 0) - 256, program[2]);
    588         assertEquals(1, program[3]);
    589         assertEquals(1, program[4]);
    590         assertEquals(123, program[5]);
    591         assertDrop(program, new byte[MIN_PKT_SIZE], 0);
    592         gen = new ApfGenerator(MIN_APF_VERSION);
    593         gen.addLoadImmediate(Register.R0, 1);
    594         gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
    595         byte[] packet123 = {0,123,0,0,0,0,0,0,0,0,0,0,0,0,0};
    596         assertPass(gen, packet123, 0);
    597         gen = new ApfGenerator(MIN_APF_VERSION);
    598         gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
    599         assertDrop(gen, packet123, 0);
    600         gen = new ApfGenerator(MIN_APF_VERSION);
    601         gen.addLoadImmediate(Register.R0, 1);
    602         gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,30,4,5}, gen.DROP_LABEL);
    603         byte[] packet12345 = {0,1,2,3,4,5,0,0,0,0,0,0,0,0,0};
    604         assertDrop(gen, packet12345, 0);
    605         gen = new ApfGenerator(MIN_APF_VERSION);
    606         gen.addLoadImmediate(Register.R0, 1);
    607         gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,3,4,5}, gen.DROP_LABEL);
    608         assertPass(gen, packet12345, 0);
    609     }
    610 
    611     @Test(expected = ApfGenerator.IllegalInstructionException.class)
    612     public void testApfGeneratorWantsV2OrGreater() throws Exception {
    613         // The minimum supported APF version is 2.
    614         new ApfGenerator(1);
    615     }
    616 
    617     @Test
    618     public void testApfDataOpcodesWantApfV3() throws IllegalInstructionException, Exception {
    619         ApfGenerator gen = new ApfGenerator(MIN_APF_VERSION);
    620         try {
    621             gen.addStoreData(Register.R0, 0);
    622             fail();
    623         } catch (IllegalInstructionException expected) {
    624             /* pass */
    625         }
    626         try {
    627             gen.addLoadData(Register.R0, 0);
    628             fail();
    629         } catch (IllegalInstructionException expected) {
    630             /* pass */
    631         }
    632     }
    633 
    634     /**
    635      * Test that the generator emits immediates using the shortest possible encoding.
    636      */
    637     @Test
    638     public void testImmediateEncoding() throws IllegalInstructionException {
    639         final int LI_OPCODE = 13 << 3;
    640         ApfGenerator gen;
    641 
    642         // 0-byte immediate: li R0, 0
    643         gen = new ApfGenerator(3);
    644         gen.addLoadImmediate(Register.R0, 0);
    645         assertProgramEquals(new byte[]{LI_OPCODE | (0 << 1)}, gen.generate());
    646 
    647         // 1-byte immediate: li R0, 42
    648         gen = new ApfGenerator(3);
    649         gen.addLoadImmediate(Register.R0, 42);
    650         assertProgramEquals(new byte[]{LI_OPCODE | (1 << 1), 42}, gen.generate());
    651 
    652         // 2-byte immediate: li R1, 0x1234
    653         gen = new ApfGenerator(3);
    654         gen.addLoadImmediate(Register.R1, 0x1234);
    655         assertProgramEquals(new byte[]{LI_OPCODE | (2 << 1) | 1 , 0x12, 0x34}, gen.generate());
    656 
    657         // 4-byte immediate: li R0, 0x12345678
    658         gen = new ApfGenerator(3);
    659         gen.addLoadImmediate(Register.R0, 0x12345678);
    660         assertProgramEquals(
    661                 new byte[]{LI_OPCODE | (3 << 1), 0x12, 0x34, 0x56, 0x78},
    662                 gen.generate());
    663     }
    664 
    665     /**
    666      * Test that the generator emits negative immediates using the shortest possible encoding.
    667      */
    668     @Test
    669     public void testNegativeImmediateEncoding() throws IllegalInstructionException {
    670         final int LI_OPCODE = 13 << 3;
    671         ApfGenerator gen;
    672 
    673         // 1-byte negative immediate: li R0, -42
    674         gen = new ApfGenerator(3);
    675         gen.addLoadImmediate(Register.R0, -42);
    676         assertProgramEquals(new byte[]{LI_OPCODE | (1 << 1), -42}, gen.generate());
    677 
    678         // 2-byte negative immediate: li R1, -0x1234
    679         gen = new ApfGenerator(3);
    680         gen.addLoadImmediate(Register.R1, -0x1122);
    681         assertProgramEquals(new byte[]{LI_OPCODE | (2 << 1) | 1, (byte)0xEE, (byte)0xDE},
    682                 gen.generate());
    683 
    684         // 4-byte negative immediate: li R0, -0x11223344
    685         gen = new ApfGenerator(3);
    686         gen.addLoadImmediate(Register.R0, -0x11223344);
    687         assertProgramEquals(
    688                 new byte[]{LI_OPCODE | (3 << 1), (byte)0xEE, (byte)0xDD, (byte)0xCC, (byte)0xBC},
    689                 gen.generate());
    690     }
    691 
    692     @Test
    693     public void testApfDataWrite() throws IllegalInstructionException, Exception {
    694         byte[] packet = new byte[MIN_PKT_SIZE];
    695         byte[] data = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
    696         byte[] expected_data = data.clone();
    697 
    698         // No memory access instructions: should leave the data segment untouched.
    699         ApfGenerator gen = new ApfGenerator(3);
    700         assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
    701 
    702         // Expect value 0x87654321 to be stored starting from address -11 from the end of the
    703         // data buffer, in big-endian order.
    704         gen = new ApfGenerator(3);
    705         gen.addLoadImmediate(Register.R0, 0x87654321);
    706         gen.addLoadImmediate(Register.R1, -5);
    707         gen.addStoreData(Register.R0, -6);  // -5 + -6 = -11 (offset +5 with data_len=16)
    708         expected_data[5] = (byte)0x87;
    709         expected_data[6] = (byte)0x65;
    710         expected_data[7] = (byte)0x43;
    711         expected_data[8] = (byte)0x21;
    712         assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
    713     }
    714 
    715     @Test
    716     public void testApfDataRead() throws IllegalInstructionException, Exception {
    717         // Program that DROPs if address 10 (-6) contains 0x87654321.
    718         ApfGenerator gen = new ApfGenerator(3);
    719         gen.addLoadImmediate(Register.R1, 10);
    720         gen.addLoadData(Register.R0, -16);  // 10 + -16 = -6 (offset +10 with data_len=16)
    721         gen.addJumpIfR0Equals(0x87654321, gen.DROP_LABEL);
    722         byte[] program = gen.generate();
    723         byte[] packet = new byte[MIN_PKT_SIZE];
    724 
    725         // Content is incorrect (last byte does not match) -> PASS
    726         byte[] data = new byte[16];
    727         data[10] = (byte)0x87;
    728         data[11] = (byte)0x65;
    729         data[12] = (byte)0x43;
    730         data[13] = (byte)0x00;  // != 0x21
    731         byte[] expected_data = data.clone();
    732         assertDataMemoryContents(PASS, program, packet, data, expected_data);
    733 
    734         // Fix the last byte -> conditional jump taken -> DROP
    735         data[13] = (byte)0x21;
    736         expected_data = data;
    737         assertDataMemoryContents(DROP, program, packet, data, expected_data);
    738     }
    739 
    740     @Test
    741     public void testApfDataReadModifyWrite() throws IllegalInstructionException, Exception {
    742         ApfGenerator gen = new ApfGenerator(3);
    743         gen.addLoadImmediate(Register.R1, -22);
    744         gen.addLoadData(Register.R0, 0);  // Load from address 32 -22 + 0 = 10
    745         gen.addAdd(0x78453412);  // 87654321 + 78453412 = FFAA7733
    746         gen.addStoreData(Register.R0, 4);  // Write back to address 32 -22 + 4 = 14
    747 
    748         byte[] packet = new byte[MIN_PKT_SIZE];
    749         byte[] data = new byte[32];
    750         data[10] = (byte)0x87;
    751         data[11] = (byte)0x65;
    752         data[12] = (byte)0x43;
    753         data[13] = (byte)0x21;
    754         byte[] expected_data = data.clone();
    755         expected_data[14] = (byte)0xFF;
    756         expected_data[15] = (byte)0xAA;
    757         expected_data[16] = (byte)0x77;
    758         expected_data[17] = (byte)0x33;
    759         assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
    760     }
    761 
    762     @Test
    763     public void testApfDataBoundChecking() throws IllegalInstructionException, Exception {
    764         byte[] packet = new byte[MIN_PKT_SIZE];
    765         byte[] data = new byte[32];
    766         byte[] expected_data = data;
    767 
    768         // Program that DROPs unconditionally. This is our the baseline.
    769         ApfGenerator gen = new ApfGenerator(3);
    770         gen.addLoadImmediate(Register.R0, 3);
    771         gen.addLoadData(Register.R1, 7);
    772         gen.addJump(gen.DROP_LABEL);
    773         assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data);
    774 
    775         // Same program as before, but this time we're trying to load past the end of the data.
    776         gen = new ApfGenerator(3);
    777         gen.addLoadImmediate(Register.R0, 20);
    778         gen.addLoadData(Register.R1, 15);  // 20 + 15 > 32
    779         gen.addJump(gen.DROP_LABEL);  // Not reached.
    780         assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
    781 
    782         // Subtracting an immediate should work...
    783         gen = new ApfGenerator(3);
    784         gen.addLoadImmediate(Register.R0, 20);
    785         gen.addLoadData(Register.R1, -4);
    786         gen.addJump(gen.DROP_LABEL);
    787         assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data);
    788 
    789         // ...and underflowing simply wraps around to the end of the buffer...
    790         gen = new ApfGenerator(3);
    791         gen.addLoadImmediate(Register.R0, 20);
    792         gen.addLoadData(Register.R1, -30);
    793         gen.addJump(gen.DROP_LABEL);
    794         assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data);
    795 
    796         // ...but doesn't allow accesses before the start of the buffer
    797         gen = new ApfGenerator(3);
    798         gen.addLoadImmediate(Register.R0, 20);
    799         gen.addLoadData(Register.R1, -1000);
    800         gen.addJump(gen.DROP_LABEL);  // Not reached.
    801         assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
    802     }
    803 
    804     /**
    805      * Generate some BPF programs, translate them to APF, then run APF and BPF programs
    806      * over packet traces and verify both programs filter out the same packets.
    807      */
    808     @Test
    809     public void testApfAgainstBpf() throws Exception {
    810         String[] tcpdump_filters = new String[]{ "udp", "tcp", "icmp", "icmp6", "udp port 53",
    811                 "arp", "dst 239.255.255.250", "arp or tcp or udp port 53", "net 192.168.1.0/24",
    812                 "arp or icmp6 or portrange 53-54", "portrange 53-54 or portrange 100-50000",
    813                 "tcp[tcpflags] & (tcp-ack|tcp-fin) != 0 and (ip[2:2] > 57 or icmp)" };
    814         String pcap_filename = stageFile(R.raw.apf);
    815         for (String tcpdump_filter : tcpdump_filters) {
    816             byte[] apf_program = Bpf2Apf.convert(compileToBpf(tcpdump_filter));
    817             assertTrue("Failed to match for filter: " + tcpdump_filter,
    818                     compareBpfApf(tcpdump_filter, pcap_filename, apf_program));
    819         }
    820     }
    821 
    822     private class MockIpClientCallback extends IpClient.Callback {
    823         private final ConditionVariable mGotApfProgram = new ConditionVariable();
    824         private byte[] mLastApfProgram;
    825 
    826         @Override
    827         public void installPacketFilter(byte[] filter) {
    828             mLastApfProgram = filter;
    829             mGotApfProgram.open();
    830         }
    831 
    832         public void resetApfProgramWait() {
    833             mGotApfProgram.close();
    834         }
    835 
    836         public byte[] getApfProgram() {
    837             assertTrue(mGotApfProgram.block(TIMEOUT_MS));
    838             return mLastApfProgram;
    839         }
    840 
    841         public void assertNoProgramUpdate() {
    842             assertFalse(mGotApfProgram.block(TIMEOUT_MS));
    843         }
    844     }
    845 
    846     private static class TestApfFilter extends ApfFilter {
    847         public final static byte[] MOCK_MAC_ADDR = {1,2,3,4,5,6};
    848 
    849         private FileDescriptor mWriteSocket;
    850         private final long mFixedTimeMs = SystemClock.elapsedRealtime();
    851 
    852         public TestApfFilter(Context context, ApfConfiguration config,
    853                 IpClient.Callback ipClientCallback, IpConnectivityLog log) throws Exception {
    854             super(context, config, InterfaceParams.getByName("lo"), ipClientCallback, log);
    855         }
    856 
    857         // Pretend an RA packet has been received and show it to ApfFilter.
    858         public void pretendPacketReceived(byte[] packet) throws IOException, ErrnoException {
    859             // ApfFilter's ReceiveThread will be waiting to read this.
    860             Os.write(mWriteSocket, packet, 0, packet.length);
    861         }
    862 
    863         @Override
    864         protected long currentTimeSeconds() {
    865             return mFixedTimeMs / DateUtils.SECOND_IN_MILLIS;
    866         }
    867 
    868         @Override
    869         void maybeStartFilter() {
    870             mHardwareAddress = MOCK_MAC_ADDR;
    871             installNewProgramLocked();
    872 
    873             // Create two sockets, "readSocket" and "mWriteSocket" and connect them together.
    874             FileDescriptor readSocket = new FileDescriptor();
    875             mWriteSocket = new FileDescriptor();
    876             try {
    877                 Os.socketpair(AF_UNIX, SOCK_STREAM, 0, mWriteSocket, readSocket);
    878             } catch (ErrnoException e) {
    879                 fail();
    880                 return;
    881             }
    882             // Now pass readSocket to ReceiveThread as if it was setup to read raw RAs.
    883             // This allows us to pretend RA packets have been recieved via pretendPacketReceived().
    884             mReceiveThread = new ReceiveThread(readSocket);
    885             mReceiveThread.start();
    886         }
    887 
    888         @Override
    889         public void shutdown() {
    890             super.shutdown();
    891             IoUtils.closeQuietly(mWriteSocket);
    892         }
    893     }
    894 
    895     private static final int ETH_HEADER_LEN = 14;
    896     private static final int ETH_DEST_ADDR_OFFSET = 0;
    897     private static final int ETH_ETHERTYPE_OFFSET = 12;
    898     private static final byte[] ETH_BROADCAST_MAC_ADDRESS =
    899             {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
    900 
    901     private static final int IPV4_VERSION_IHL_OFFSET = ETH_HEADER_LEN + 0;
    902     private static final int IPV4_PROTOCOL_OFFSET = ETH_HEADER_LEN + 9;
    903     private static final int IPV4_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 16;
    904     private static final byte[] IPV4_BROADCAST_ADDRESS =
    905             {(byte) 255, (byte) 255, (byte) 255, (byte) 255};
    906 
    907     private static final int IPV6_NEXT_HEADER_OFFSET = ETH_HEADER_LEN + 6;
    908     private static final int IPV6_HEADER_LEN = 40;
    909     private static final int IPV6_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 24;
    910     // The IPv6 all nodes address ff02::1
    911     private static final byte[] IPV6_ALL_NODES_ADDRESS =
    912             { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
    913     private static final byte[] IPV6_ALL_ROUTERS_ADDRESS =
    914             { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 };
    915 
    916     private static final int ICMP6_TYPE_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN;
    917     private static final int ICMP6_ROUTER_SOLICITATION = 133;
    918     private static final int ICMP6_ROUTER_ADVERTISEMENT = 134;
    919     private static final int ICMP6_NEIGHBOR_SOLICITATION = 135;
    920     private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136;
    921 
    922     private static final int ICMP6_RA_HEADER_LEN = 16;
    923     private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET =
    924             ETH_HEADER_LEN + IPV6_HEADER_LEN + 6;
    925     private static final int ICMP6_RA_CHECKSUM_OFFSET =
    926             ETH_HEADER_LEN + IPV6_HEADER_LEN + 2;
    927     private static final int ICMP6_RA_OPTION_OFFSET =
    928             ETH_HEADER_LEN + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN;
    929 
    930     private static final int ICMP6_PREFIX_OPTION_TYPE = 3;
    931     private static final int ICMP6_PREFIX_OPTION_LEN = 32;
    932     private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET = 4;
    933     private static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET = 8;
    934 
    935     // From RFC6106: Recursive DNS Server option
    936     private static final int ICMP6_RDNSS_OPTION_TYPE = 25;
    937     // From RFC6106: DNS Search List option
    938     private static final int ICMP6_DNSSL_OPTION_TYPE = 31;
    939 
    940     // From RFC4191: Route Information option
    941     private static final int ICMP6_ROUTE_INFO_OPTION_TYPE = 24;
    942     // Above three options all have the same format:
    943     private static final int ICMP6_4_BYTE_OPTION_LEN = 8;
    944     private static final int ICMP6_4_BYTE_LIFETIME_OFFSET = 4;
    945     private static final int ICMP6_4_BYTE_LIFETIME_LEN = 4;
    946 
    947     private static final int UDP_HEADER_LEN = 8;
    948     private static final int UDP_DESTINATION_PORT_OFFSET = ETH_HEADER_LEN + 22;
    949 
    950     private static final int DHCP_CLIENT_PORT = 68;
    951     private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 48;
    952 
    953     private static final int ARP_HEADER_OFFSET = ETH_HEADER_LEN;
    954     private static final byte[] ARP_IPV4_REQUEST_HEADER = {
    955             0, 1, // Hardware type: Ethernet (1)
    956             8, 0, // Protocol type: IP (0x0800)
    957             6,    // Hardware size: 6
    958             4,    // Protocol size: 4
    959             0, 1  // Opcode: request (1)
    960     };
    961     private static final byte[] ARP_IPV4_REPLY_HEADER = {
    962             0, 1, // Hardware type: Ethernet (1)
    963             8, 0, // Protocol type: IP (0x0800)
    964             6,    // Hardware size: 6
    965             4,    // Protocol size: 4
    966             0, 2  // Opcode: reply (2)
    967     };
    968     private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ETH_HEADER_LEN + 24;
    969 
    970     private static final byte[] MOCK_IPV4_ADDR           = {10, 0, 0, 1};
    971     private static final byte[] MOCK_BROADCAST_IPV4_ADDR = {10, 0, 31, (byte) 255}; // prefix = 19
    972     private static final byte[] MOCK_MULTICAST_IPV4_ADDR = {(byte) 224, 0, 0, 1};
    973     private static final byte[] ANOTHER_IPV4_ADDR        = {10, 0, 0, 2};
    974     private static final byte[] IPV4_ANY_HOST_ADDR       = {0, 0, 0, 0};
    975 
    976     // Helper to initialize a default apfFilter.
    977     private ApfFilter setupApfFilter(IpClient.Callback ipClientCallback, ApfConfiguration config)
    978             throws Exception {
    979         LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
    980         LinkProperties lp = new LinkProperties();
    981         lp.addLinkAddress(link);
    982         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
    983         apfFilter.setLinkProperties(lp);
    984         return apfFilter;
    985     }
    986 
    987     @Test
    988     public void testApfFilterIPv4() throws Exception {
    989         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
    990         LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
    991         LinkProperties lp = new LinkProperties();
    992         lp.addLinkAddress(link);
    993 
    994         ApfConfiguration config = getDefaultConfig();
    995         config.multicastFilter = DROP_MULTICAST;
    996         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
    997         apfFilter.setLinkProperties(lp);
    998 
    999         byte[] program = ipClientCallback.getApfProgram();
   1000 
   1001         // Verify empty packet of 100 zero bytes is passed
   1002         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
   1003         assertPass(program, packet.array());
   1004 
   1005         // Verify unicast IPv4 packet is passed
   1006         put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
   1007         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
   1008         put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_IPV4_ADDR);
   1009         assertPass(program, packet.array());
   1010 
   1011         // Verify L2 unicast to IPv4 broadcast addresses is dropped (b/30231088)
   1012         put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
   1013         assertDrop(program, packet.array());
   1014         put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR);
   1015         assertDrop(program, packet.array());
   1016 
   1017         // Verify multicast/broadcast IPv4, not DHCP to us, is dropped
   1018         put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
   1019         assertDrop(program, packet.array());
   1020         packet.put(IPV4_VERSION_IHL_OFFSET, (byte)0x45);
   1021         assertDrop(program, packet.array());
   1022         packet.put(IPV4_PROTOCOL_OFFSET, (byte)IPPROTO_UDP);
   1023         assertDrop(program, packet.array());
   1024         packet.putShort(UDP_DESTINATION_PORT_OFFSET, (short)DHCP_CLIENT_PORT);
   1025         assertDrop(program, packet.array());
   1026         put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_MULTICAST_IPV4_ADDR);
   1027         assertDrop(program, packet.array());
   1028         put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR);
   1029         assertDrop(program, packet.array());
   1030         put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
   1031         assertDrop(program, packet.array());
   1032 
   1033         // Verify broadcast IPv4 DHCP to us is passed
   1034         put(packet, DHCP_CLIENT_MAC_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
   1035         assertPass(program, packet.array());
   1036 
   1037         // Verify unicast IPv4 DHCP to us is passed
   1038         put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
   1039         assertPass(program, packet.array());
   1040 
   1041         apfFilter.shutdown();
   1042     }
   1043 
   1044     @Test
   1045     public void testApfFilterIPv6() throws Exception {
   1046         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
   1047         ApfConfiguration config = getDefaultConfig();
   1048         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
   1049         byte[] program = ipClientCallback.getApfProgram();
   1050 
   1051         // Verify empty IPv6 packet is passed
   1052         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
   1053         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
   1054         assertPass(program, packet.array());
   1055 
   1056         // Verify empty ICMPv6 packet is passed
   1057         packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
   1058         assertPass(program, packet.array());
   1059 
   1060         // Verify empty ICMPv6 NA packet is passed
   1061         packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_NEIGHBOR_ANNOUNCEMENT);
   1062         assertPass(program, packet.array());
   1063 
   1064         // Verify ICMPv6 NA to ff02::1 is dropped
   1065         put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_NODES_ADDRESS);
   1066         assertDrop(program, packet.array());
   1067 
   1068         // Verify ICMPv6 RS to any is dropped
   1069         packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_SOLICITATION);
   1070         assertDrop(program, packet.array());
   1071         put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_ROUTERS_ADDRESS);
   1072         assertDrop(program, packet.array());
   1073 
   1074         apfFilter.shutdown();
   1075     }
   1076 
   1077     @Test
   1078     public void testApfFilterMulticast() throws Exception {
   1079         final byte[] unicastIpv4Addr   = {(byte)192,0,2,63};
   1080         final byte[] broadcastIpv4Addr = {(byte)192,0,2,(byte)255};
   1081         final byte[] multicastIpv4Addr = {(byte)224,0,0,1};
   1082         final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb};
   1083 
   1084         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
   1085         LinkAddress link = new LinkAddress(InetAddress.getByAddress(unicastIpv4Addr), 24);
   1086         LinkProperties lp = new LinkProperties();
   1087         lp.addLinkAddress(link);
   1088 
   1089         ApfConfiguration config = getDefaultConfig();
   1090         config.ieee802_3Filter = DROP_802_3_FRAMES;
   1091         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
   1092         apfFilter.setLinkProperties(lp);
   1093 
   1094         byte[] program = ipClientCallback.getApfProgram();
   1095 
   1096         // Construct IPv4 and IPv6 multicast packets.
   1097         ByteBuffer mcastv4packet = ByteBuffer.wrap(new byte[100]);
   1098         mcastv4packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
   1099         put(mcastv4packet, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr);
   1100 
   1101         ByteBuffer mcastv6packet = ByteBuffer.wrap(new byte[100]);
   1102         mcastv6packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
   1103         mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_UDP);
   1104         put(mcastv6packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr);
   1105 
   1106         // Construct IPv4 broadcast packet.
   1107         ByteBuffer bcastv4packet1 = ByteBuffer.wrap(new byte[100]);
   1108         bcastv4packet1.put(ETH_BROADCAST_MAC_ADDRESS);
   1109         bcastv4packet1.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
   1110         put(bcastv4packet1, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr);
   1111 
   1112         ByteBuffer bcastv4packet2 = ByteBuffer.wrap(new byte[100]);
   1113         bcastv4packet2.put(ETH_BROADCAST_MAC_ADDRESS);
   1114         bcastv4packet2.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
   1115         put(bcastv4packet2, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
   1116 
   1117         // Construct IPv4 broadcast with L2 unicast address packet (b/30231088).
   1118         ByteBuffer bcastv4unicastl2packet = ByteBuffer.wrap(new byte[100]);
   1119         bcastv4unicastl2packet.put(TestApfFilter.MOCK_MAC_ADDR);
   1120         bcastv4unicastl2packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
   1121         put(bcastv4unicastl2packet, IPV4_DEST_ADDR_OFFSET, broadcastIpv4Addr);
   1122 
   1123         // Verify initially disabled multicast filter is off
   1124         assertPass(program, mcastv4packet.array());
   1125         assertPass(program, mcastv6packet.array());
   1126         assertPass(program, bcastv4packet1.array());
   1127         assertPass(program, bcastv4packet2.array());
   1128         assertPass(program, bcastv4unicastl2packet.array());
   1129 
   1130         // Turn on multicast filter and verify it works
   1131         ipClientCallback.resetApfProgramWait();
   1132         apfFilter.setMulticastFilter(true);
   1133         program = ipClientCallback.getApfProgram();
   1134         assertDrop(program, mcastv4packet.array());
   1135         assertDrop(program, mcastv6packet.array());
   1136         assertDrop(program, bcastv4packet1.array());
   1137         assertDrop(program, bcastv4packet2.array());
   1138         assertDrop(program, bcastv4unicastl2packet.array());
   1139 
   1140         // Turn off multicast filter and verify it's off
   1141         ipClientCallback.resetApfProgramWait();
   1142         apfFilter.setMulticastFilter(false);
   1143         program = ipClientCallback.getApfProgram();
   1144         assertPass(program, mcastv4packet.array());
   1145         assertPass(program, mcastv6packet.array());
   1146         assertPass(program, bcastv4packet1.array());
   1147         assertPass(program, bcastv4packet2.array());
   1148         assertPass(program, bcastv4unicastl2packet.array());
   1149 
   1150         // Verify it can be initialized to on
   1151         ipClientCallback.resetApfProgramWait();
   1152         apfFilter.shutdown();
   1153         config.multicastFilter = DROP_MULTICAST;
   1154         config.ieee802_3Filter = DROP_802_3_FRAMES;
   1155         apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
   1156         apfFilter.setLinkProperties(lp);
   1157         program = ipClientCallback.getApfProgram();
   1158         assertDrop(program, mcastv4packet.array());
   1159         assertDrop(program, mcastv6packet.array());
   1160         assertDrop(program, bcastv4packet1.array());
   1161         assertDrop(program, bcastv4unicastl2packet.array());
   1162 
   1163         // Verify that ICMPv6 multicast is not dropped.
   1164         mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
   1165         assertPass(program, mcastv6packet.array());
   1166 
   1167         apfFilter.shutdown();
   1168     }
   1169 
   1170     @Test
   1171     public void testApfFilterMulticastPingWhileDozing() throws Exception {
   1172         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
   1173         ApfFilter apfFilter = setupApfFilter(ipClientCallback, getDefaultConfig());
   1174 
   1175         // Construct a multicast ICMPv6 ECHO request.
   1176         final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb};
   1177         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
   1178         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
   1179         packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
   1180         packet.put(ICMP6_TYPE_OFFSET, (byte)ICMPV6_ECHO_REQUEST_TYPE);
   1181         put(packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr);
   1182 
   1183         // Normally, we let multicast pings alone...
   1184         assertPass(ipClientCallback.getApfProgram(), packet.array());
   1185 
   1186         // ...and even while dozing...
   1187         apfFilter.setDozeMode(true);
   1188         assertPass(ipClientCallback.getApfProgram(), packet.array());
   1189 
   1190         // ...but when the multicast filter is also enabled, drop the multicast pings to save power.
   1191         apfFilter.setMulticastFilter(true);
   1192         assertDrop(ipClientCallback.getApfProgram(), packet.array());
   1193 
   1194         // However, we should still let through all other ICMPv6 types.
   1195         ByteBuffer raPacket = ByteBuffer.wrap(packet.array().clone());
   1196         raPacket.put(ICMP6_TYPE_OFFSET, (byte)ICMPV6_ROUTER_ADVERTISEMENT);
   1197         assertPass(ipClientCallback.getApfProgram(), raPacket.array());
   1198 
   1199         // Now wake up from doze mode to ensure that we no longer drop the packets.
   1200         // (The multicast filter is still enabled at this point).
   1201         apfFilter.setDozeMode(false);
   1202         assertPass(ipClientCallback.getApfProgram(), packet.array());
   1203 
   1204         apfFilter.shutdown();
   1205     }
   1206 
   1207     @Test
   1208     public void testApfFilter802_3() throws Exception {
   1209         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
   1210         ApfConfiguration config = getDefaultConfig();
   1211         ApfFilter apfFilter = setupApfFilter(ipClientCallback, config);
   1212         byte[] program = ipClientCallback.getApfProgram();
   1213 
   1214         // Verify empty packet of 100 zero bytes is passed
   1215         // Note that eth-type = 0 makes it an IEEE802.3 frame
   1216         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
   1217         assertPass(program, packet.array());
   1218 
   1219         // Verify empty packet with IPv4 is passed
   1220         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
   1221         assertPass(program, packet.array());
   1222 
   1223         // Verify empty IPv6 packet is passed
   1224         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
   1225         assertPass(program, packet.array());
   1226 
   1227         // Now turn on the filter
   1228         ipClientCallback.resetApfProgramWait();
   1229         apfFilter.shutdown();
   1230         config.ieee802_3Filter = DROP_802_3_FRAMES;
   1231         apfFilter = setupApfFilter(ipClientCallback, config);
   1232         program = ipClientCallback.getApfProgram();
   1233 
   1234         // Verify that IEEE802.3 frame is dropped
   1235         // In this case ethtype is used for payload length
   1236         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)(100 - 14));
   1237         assertDrop(program, packet.array());
   1238 
   1239         // Verify that IPv4 (as example of Ethernet II) frame will pass
   1240         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
   1241         assertPass(program, packet.array());
   1242 
   1243         // Verify that IPv6 (as example of Ethernet II) frame will pass
   1244         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
   1245         assertPass(program, packet.array());
   1246 
   1247         apfFilter.shutdown();
   1248     }
   1249 
   1250     @Test
   1251     public void testApfFilterEthTypeBL() throws Exception {
   1252         final int[] emptyBlackList = {};
   1253         final int[] ipv4BlackList = {ETH_P_IP};
   1254         final int[] ipv4Ipv6BlackList = {ETH_P_IP, ETH_P_IPV6};
   1255 
   1256         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
   1257         ApfConfiguration config = getDefaultConfig();
   1258         ApfFilter apfFilter = setupApfFilter(ipClientCallback, config);
   1259         byte[] program = ipClientCallback.getApfProgram();
   1260 
   1261         // Verify empty packet of 100 zero bytes is passed
   1262         // Note that eth-type = 0 makes it an IEEE802.3 frame
   1263         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
   1264         assertPass(program, packet.array());
   1265 
   1266         // Verify empty packet with IPv4 is passed
   1267         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
   1268         assertPass(program, packet.array());
   1269 
   1270         // Verify empty IPv6 packet is passed
   1271         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
   1272         assertPass(program, packet.array());
   1273 
   1274         // Now add IPv4 to the black list
   1275         ipClientCallback.resetApfProgramWait();
   1276         apfFilter.shutdown();
   1277         config.ethTypeBlackList = ipv4BlackList;
   1278         apfFilter = setupApfFilter(ipClientCallback, config);
   1279         program = ipClientCallback.getApfProgram();
   1280 
   1281         // Verify that IPv4 frame will be dropped
   1282         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
   1283         assertDrop(program, packet.array());
   1284 
   1285         // Verify that IPv6 frame will pass
   1286         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
   1287         assertPass(program, packet.array());
   1288 
   1289         // Now let us have both IPv4 and IPv6 in the black list
   1290         ipClientCallback.resetApfProgramWait();
   1291         apfFilter.shutdown();
   1292         config.ethTypeBlackList = ipv4Ipv6BlackList;
   1293         apfFilter = setupApfFilter(ipClientCallback, config);
   1294         program = ipClientCallback.getApfProgram();
   1295 
   1296         // Verify that IPv4 frame will be dropped
   1297         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
   1298         assertDrop(program, packet.array());
   1299 
   1300         // Verify that IPv6 frame will be dropped
   1301         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
   1302         assertDrop(program, packet.array());
   1303 
   1304         apfFilter.shutdown();
   1305     }
   1306 
   1307     private byte[] getProgram(MockIpClientCallback cb, ApfFilter filter, LinkProperties lp) {
   1308         cb.resetApfProgramWait();
   1309         filter.setLinkProperties(lp);
   1310         return cb.getApfProgram();
   1311     }
   1312 
   1313     private void verifyArpFilter(byte[] program, int filterResult) {
   1314         // Verify ARP request packet
   1315         assertPass(program, arpRequestBroadcast(MOCK_IPV4_ADDR));
   1316         assertVerdict(filterResult, program, arpRequestBroadcast(ANOTHER_IPV4_ADDR));
   1317         assertDrop(program, arpRequestBroadcast(IPV4_ANY_HOST_ADDR));
   1318 
   1319         // Verify unicast ARP reply packet is always accepted.
   1320         assertPass(program, arpReplyUnicast(MOCK_IPV4_ADDR));
   1321         assertPass(program, arpReplyUnicast(ANOTHER_IPV4_ADDR));
   1322         assertPass(program, arpReplyUnicast(IPV4_ANY_HOST_ADDR));
   1323 
   1324         // Verify GARP reply packets are always filtered
   1325         assertDrop(program, garpReply());
   1326     }
   1327 
   1328     @Test
   1329     public void testApfFilterArp() throws Exception {
   1330         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
   1331         ApfConfiguration config = getDefaultConfig();
   1332         config.multicastFilter = DROP_MULTICAST;
   1333         config.ieee802_3Filter = DROP_802_3_FRAMES;
   1334         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
   1335 
   1336         // Verify initially ARP request filter is off, and GARP filter is on.
   1337         verifyArpFilter(ipClientCallback.getApfProgram(), PASS);
   1338 
   1339         // Inform ApfFilter of our address and verify ARP filtering is on
   1340         LinkAddress linkAddress = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 24);
   1341         LinkProperties lp = new LinkProperties();
   1342         assertTrue(lp.addLinkAddress(linkAddress));
   1343         verifyArpFilter(getProgram(ipClientCallback, apfFilter, lp), DROP);
   1344 
   1345         // Inform ApfFilter of loss of IP and verify ARP filtering is off
   1346         verifyArpFilter(getProgram(ipClientCallback, apfFilter, new LinkProperties()), PASS);
   1347 
   1348         apfFilter.shutdown();
   1349     }
   1350 
   1351     private static byte[] arpRequestBroadcast(byte[] tip) {
   1352         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
   1353         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
   1354         put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
   1355         put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
   1356         put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip);
   1357         return packet.array();
   1358     }
   1359 
   1360     private static byte[] arpReplyUnicast(byte[] tip) {
   1361         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
   1362         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
   1363         put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
   1364         put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip);
   1365         return packet.array();
   1366     }
   1367 
   1368     private static byte[] garpReply() {
   1369         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
   1370         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
   1371         put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
   1372         put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
   1373         put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, IPV4_ANY_HOST_ADDR);
   1374         return packet.array();
   1375     }
   1376 
   1377     // Verify that the last program pushed to the IpClient.Callback properly filters the
   1378     // given packet for the given lifetime.
   1379     private void verifyRaLifetime(byte[] program, ByteBuffer packet, int lifetime) {
   1380         final int FRACTION_OF_LIFETIME = 6;
   1381         final int ageLimit = lifetime / FRACTION_OF_LIFETIME;
   1382 
   1383         // Verify new program should drop RA for 1/6th its lifetime and pass afterwards.
   1384         assertDrop(program, packet.array());
   1385         assertDrop(program, packet.array(), ageLimit);
   1386         assertPass(program, packet.array(), ageLimit + 1);
   1387         assertPass(program, packet.array(), lifetime);
   1388         // Verify RA checksum is ignored
   1389         final short originalChecksum = packet.getShort(ICMP6_RA_CHECKSUM_OFFSET);
   1390         packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)12345);
   1391         assertDrop(program, packet.array());
   1392         packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)-12345);
   1393         assertDrop(program, packet.array());
   1394         packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, originalChecksum);
   1395 
   1396         // Verify other changes to RA make it not match filter
   1397         final byte originalFirstByte = packet.get(0);
   1398         packet.put(0, (byte)-1);
   1399         assertPass(program, packet.array());
   1400         packet.put(0, (byte)0);
   1401         assertDrop(program, packet.array());
   1402         packet.put(0, originalFirstByte);
   1403     }
   1404 
   1405     // Test that when ApfFilter is shown the given packet, it generates a program to filter it
   1406     // for the given lifetime.
   1407     private void verifyRaLifetime(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback,
   1408             ByteBuffer packet, int lifetime) throws IOException, ErrnoException {
   1409         // Verify new program generated if ApfFilter witnesses RA
   1410         ipClientCallback.resetApfProgramWait();
   1411         apfFilter.pretendPacketReceived(packet.array());
   1412         byte[] program = ipClientCallback.getApfProgram();
   1413         verifyRaLifetime(program, packet, lifetime);
   1414     }
   1415 
   1416     private void verifyRaEvent(RaEvent expected) {
   1417         ArgumentCaptor<Parcelable> captor = ArgumentCaptor.forClass(Parcelable.class);
   1418         verify(mLog, atLeastOnce()).log(captor.capture());
   1419         RaEvent got = lastRaEvent(captor.getAllValues());
   1420         if (!raEventEquals(expected, got)) {
   1421             assertEquals(expected, got);  // fail for printing an assertion error message.
   1422         }
   1423     }
   1424 
   1425     private RaEvent lastRaEvent(List<Parcelable> events) {
   1426         RaEvent got = null;
   1427         for (Parcelable ev : events) {
   1428             if (ev instanceof RaEvent) {
   1429                 got = (RaEvent) ev;
   1430             }
   1431         }
   1432         return got;
   1433     }
   1434 
   1435     private boolean raEventEquals(RaEvent ev1, RaEvent ev2) {
   1436         return (ev1 != null) && (ev2 != null)
   1437                 && (ev1.routerLifetime == ev2.routerLifetime)
   1438                 && (ev1.prefixValidLifetime == ev2.prefixValidLifetime)
   1439                 && (ev1.prefixPreferredLifetime == ev2.prefixPreferredLifetime)
   1440                 && (ev1.routeInfoLifetime == ev2.routeInfoLifetime)
   1441                 && (ev1.rdnssLifetime == ev2.rdnssLifetime)
   1442                 && (ev1.dnsslLifetime == ev2.dnsslLifetime);
   1443     }
   1444 
   1445     private void assertInvalidRa(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback,
   1446             ByteBuffer packet) throws IOException, ErrnoException {
   1447         ipClientCallback.resetApfProgramWait();
   1448         apfFilter.pretendPacketReceived(packet.array());
   1449         ipClientCallback.assertNoProgramUpdate();
   1450     }
   1451 
   1452     @Test
   1453     public void testApfFilterRa() throws Exception {
   1454         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
   1455         ApfConfiguration config = getDefaultConfig();
   1456         config.multicastFilter = DROP_MULTICAST;
   1457         config.ieee802_3Filter = DROP_802_3_FRAMES;
   1458         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
   1459         byte[] program = ipClientCallback.getApfProgram();
   1460 
   1461         final int ROUTER_LIFETIME = 1000;
   1462         final int PREFIX_VALID_LIFETIME = 200;
   1463         final int PREFIX_PREFERRED_LIFETIME = 100;
   1464         final int RDNSS_LIFETIME  = 300;
   1465         final int ROUTE_LIFETIME  = 400;
   1466         // Note that lifetime of 2000 will be ignored in favor of shorter route lifetime of 1000.
   1467         final int DNSSL_LIFETIME  = 2000;
   1468         final int VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET = ETH_HEADER_LEN;
   1469         // IPv6, traffic class = 0, flow label = 0x12345
   1470         final int VERSION_TRAFFIC_CLASS_FLOW_LABEL = 0x60012345;
   1471 
   1472         // Verify RA is passed the first time
   1473         ByteBuffer basePacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]);
   1474         basePacket.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
   1475         basePacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET,
   1476                 VERSION_TRAFFIC_CLASS_FLOW_LABEL);
   1477         basePacket.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
   1478         basePacket.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_ADVERTISEMENT);
   1479         basePacket.putShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET, (short)ROUTER_LIFETIME);
   1480         basePacket.position(IPV6_DEST_ADDR_OFFSET);
   1481         basePacket.put(IPV6_ALL_NODES_ADDRESS);
   1482         assertPass(program, basePacket.array());
   1483 
   1484         verifyRaLifetime(apfFilter, ipClientCallback, basePacket, ROUTER_LIFETIME);
   1485         verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, -1));
   1486 
   1487         ByteBuffer newFlowLabelPacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]);
   1488         basePacket.clear();
   1489         newFlowLabelPacket.put(basePacket);
   1490         // Check that changes are ignored in every byte of the flow label.
   1491         newFlowLabelPacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET,
   1492                 VERSION_TRAFFIC_CLASS_FLOW_LABEL + 0x11111);
   1493 
   1494         // Ensure zero-length options cause the packet to be silently skipped.
   1495         // Do this before we test other packets. http://b/29586253
   1496         ByteBuffer zeroLengthOptionPacket = ByteBuffer.wrap(
   1497                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
   1498         basePacket.clear();
   1499         zeroLengthOptionPacket.put(basePacket);
   1500         zeroLengthOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE);
   1501         zeroLengthOptionPacket.put((byte)0);
   1502         assertInvalidRa(apfFilter, ipClientCallback, zeroLengthOptionPacket);
   1503 
   1504         // Generate several RAs with different options and lifetimes, and verify when
   1505         // ApfFilter is shown these packets, it generates programs to filter them for the
   1506         // appropriate lifetime.
   1507         ByteBuffer prefixOptionPacket = ByteBuffer.wrap(
   1508                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_LEN]);
   1509         basePacket.clear();
   1510         prefixOptionPacket.put(basePacket);
   1511         prefixOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE);
   1512         prefixOptionPacket.put((byte)(ICMP6_PREFIX_OPTION_LEN / 8));
   1513         prefixOptionPacket.putInt(
   1514                 ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET,
   1515                 PREFIX_PREFERRED_LIFETIME);
   1516         prefixOptionPacket.putInt(
   1517                 ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET,
   1518                 PREFIX_VALID_LIFETIME);
   1519         verifyRaLifetime(
   1520                 apfFilter, ipClientCallback, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
   1521         verifyRaEvent(new RaEvent(
   1522                 ROUTER_LIFETIME, PREFIX_VALID_LIFETIME, PREFIX_PREFERRED_LIFETIME, -1, -1, -1));
   1523 
   1524         ByteBuffer rdnssOptionPacket = ByteBuffer.wrap(
   1525                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
   1526         basePacket.clear();
   1527         rdnssOptionPacket.put(basePacket);
   1528         rdnssOptionPacket.put((byte)ICMP6_RDNSS_OPTION_TYPE);
   1529         rdnssOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
   1530         rdnssOptionPacket.putInt(
   1531                 ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, RDNSS_LIFETIME);
   1532         verifyRaLifetime(apfFilter, ipClientCallback, rdnssOptionPacket, RDNSS_LIFETIME);
   1533         verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, RDNSS_LIFETIME, -1));
   1534 
   1535         ByteBuffer routeInfoOptionPacket = ByteBuffer.wrap(
   1536                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
   1537         basePacket.clear();
   1538         routeInfoOptionPacket.put(basePacket);
   1539         routeInfoOptionPacket.put((byte)ICMP6_ROUTE_INFO_OPTION_TYPE);
   1540         routeInfoOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
   1541         routeInfoOptionPacket.putInt(
   1542                 ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, ROUTE_LIFETIME);
   1543         verifyRaLifetime(apfFilter, ipClientCallback, routeInfoOptionPacket, ROUTE_LIFETIME);
   1544         verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, ROUTE_LIFETIME, -1, -1));
   1545 
   1546         ByteBuffer dnsslOptionPacket = ByteBuffer.wrap(
   1547                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
   1548         basePacket.clear();
   1549         dnsslOptionPacket.put(basePacket);
   1550         dnsslOptionPacket.put((byte)ICMP6_DNSSL_OPTION_TYPE);
   1551         dnsslOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
   1552         dnsslOptionPacket.putInt(
   1553                 ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, DNSSL_LIFETIME);
   1554         verifyRaLifetime(apfFilter, ipClientCallback, dnsslOptionPacket, ROUTER_LIFETIME);
   1555         verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, DNSSL_LIFETIME));
   1556 
   1557         // Verify that current program filters all five RAs:
   1558         program = ipClientCallback.getApfProgram();
   1559         verifyRaLifetime(program, basePacket, ROUTER_LIFETIME);
   1560         verifyRaLifetime(program, newFlowLabelPacket, ROUTER_LIFETIME);
   1561         verifyRaLifetime(program, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
   1562         verifyRaLifetime(program, rdnssOptionPacket, RDNSS_LIFETIME);
   1563         verifyRaLifetime(program, routeInfoOptionPacket, ROUTE_LIFETIME);
   1564         verifyRaLifetime(program, dnsslOptionPacket, ROUTER_LIFETIME);
   1565 
   1566         apfFilter.shutdown();
   1567     }
   1568 
   1569     /**
   1570      * Stage a file for testing, i.e. make it native accessible. Given a resource ID,
   1571      * copy that resource into the app's data directory and return the path to it.
   1572      */
   1573     private String stageFile(int rawId) throws Exception {
   1574         File file = new File(InstrumentationRegistry.getContext().getFilesDir(), "staged_file");
   1575         new File(file.getParent()).mkdirs();
   1576         InputStream in = null;
   1577         OutputStream out = null;
   1578         try {
   1579             in = InstrumentationRegistry.getContext().getResources().openRawResource(rawId);
   1580             out = new FileOutputStream(file);
   1581             Streams.copy(in, out);
   1582         } finally {
   1583             if (in != null) in.close();
   1584             if (out != null) out.close();
   1585         }
   1586         return file.getAbsolutePath();
   1587     }
   1588 
   1589     private static void put(ByteBuffer buffer, int position, byte[] bytes) {
   1590         final int original = buffer.position();
   1591         buffer.position(position);
   1592         buffer.put(bytes);
   1593         buffer.position(original);
   1594     }
   1595 
   1596     @Test
   1597     public void testRaParsing() throws Exception {
   1598         final int maxRandomPacketSize = 512;
   1599         final Random r = new Random();
   1600         MockIpClientCallback cb = new MockIpClientCallback();
   1601         ApfConfiguration config = getDefaultConfig();
   1602         config.multicastFilter = DROP_MULTICAST;
   1603         config.ieee802_3Filter = DROP_802_3_FRAMES;
   1604         TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog);
   1605         for (int i = 0; i < 1000; i++) {
   1606             byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
   1607             r.nextBytes(packet);
   1608             try {
   1609                 apfFilter.new Ra(packet, packet.length);
   1610             } catch (ApfFilter.InvalidRaException e) {
   1611             } catch (Exception e) {
   1612                 throw new Exception("bad packet: " + HexDump.toHexString(packet), e);
   1613             }
   1614         }
   1615     }
   1616 
   1617     @Test
   1618     public void testRaProcessing() throws Exception {
   1619         final int maxRandomPacketSize = 512;
   1620         final Random r = new Random();
   1621         MockIpClientCallback cb = new MockIpClientCallback();
   1622         ApfConfiguration config = getDefaultConfig();
   1623         config.multicastFilter = DROP_MULTICAST;
   1624         config.ieee802_3Filter = DROP_802_3_FRAMES;
   1625         TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog);
   1626         for (int i = 0; i < 1000; i++) {
   1627             byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
   1628             r.nextBytes(packet);
   1629             try {
   1630                 apfFilter.processRa(packet, packet.length);
   1631             } catch (Exception e) {
   1632                 throw new Exception("bad packet: " + HexDump.toHexString(packet), e);
   1633             }
   1634         }
   1635     }
   1636 
   1637     /**
   1638      * Call the APF interpreter to run {@code program} on {@code packet} with persistent memory
   1639      * segment {@data} pretending the filter was installed {@code filter_age} seconds ago.
   1640      */
   1641     private native static int apfSimulate(byte[] program, byte[] packet, byte[] data,
   1642         int filter_age);
   1643 
   1644     /**
   1645      * Compile a tcpdump human-readable filter (e.g. "icmp" or "tcp port 54") into a BPF
   1646      * prorgam and return a human-readable dump of the BPF program identical to "tcpdump -d".
   1647      */
   1648     private native static String compileToBpf(String filter);
   1649 
   1650     /**
   1651      * Open packet capture file {@code pcap_filename} and filter the packets using tcpdump
   1652      * human-readable filter (e.g. "icmp" or "tcp port 54") compiled to a BPF program and
   1653      * at the same time using APF program {@code apf_program}.  Return {@code true} if
   1654      * both APF and BPF programs filter out exactly the same packets.
   1655      */
   1656     private native static boolean compareBpfApf(String filter, String pcap_filename,
   1657             byte[] apf_program);
   1658 
   1659     @Test
   1660     public void testBroadcastAddress() throws Exception {
   1661         assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 0));
   1662         assertEqualsIp("0.0.0.0", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 32));
   1663         assertEqualsIp("0.0.3.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 22));
   1664         assertEqualsIp("0.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 8));
   1665 
   1666         assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 0));
   1667         assertEqualsIp("10.0.0.1", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 32));
   1668         assertEqualsIp("10.0.0.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 24));
   1669         assertEqualsIp("10.0.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 16));
   1670     }
   1671 
   1672     public void assertEqualsIp(String expected, int got) throws Exception {
   1673         int want = bytesToBEInt(InetAddress.getByName(expected).getAddress());
   1674         assertEquals(want, got);
   1675     }
   1676 }
   1677