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 android.net.LinkAddress;
     20 import android.net.LinkProperties;
     21 import android.net.NetworkUtils;
     22 import android.net.apf.ApfCapabilities;
     23 import android.net.apf.ApfFilter;
     24 import android.net.apf.ApfGenerator;
     25 import android.net.apf.ApfGenerator.IllegalInstructionException;
     26 import android.net.apf.ApfGenerator.Register;
     27 import android.net.ip.IpManager;
     28 import android.net.metrics.IpConnectivityLog;
     29 import android.net.metrics.RaEvent;
     30 import android.os.ConditionVariable;
     31 import android.os.Parcelable;
     32 import android.os.SystemClock;
     33 import android.system.ErrnoException;
     34 import android.system.Os;
     35 import android.test.AndroidTestCase;
     36 import android.text.format.DateUtils;
     37 import android.test.suitebuilder.annotation.SmallTest;
     38 import static android.system.OsConstants.*;
     39 
     40 import com.android.frameworks.tests.net.R;
     41 import com.android.internal.util.HexDump;
     42 
     43 import org.mockito.ArgumentCaptor;
     44 import org.mockito.Mock;
     45 import org.mockito.MockitoAnnotations;
     46 import static org.mockito.Mockito.atLeastOnce;
     47 import static org.mockito.Mockito.verify;
     48 
     49 import java.io.File;
     50 import java.io.FileDescriptor;
     51 import java.io.FileOutputStream;
     52 import java.io.IOException;
     53 import java.io.InputStream;
     54 import java.io.OutputStream;
     55 import java.net.InetAddress;
     56 import java.net.NetworkInterface;
     57 import java.nio.ByteBuffer;
     58 import java.util.List;
     59 import java.util.Random;
     60 
     61 import libcore.io.IoUtils;
     62 import libcore.io.Streams;
     63 
     64 /**
     65  * Tests for APF program generator and interpreter.
     66  *
     67  * Build, install and run with:
     68  *  runtest frameworks-services -c android.net.apf.ApfTest
     69  */
     70 public class ApfTest extends AndroidTestCase {
     71     private static final int TIMEOUT_MS = 500;
     72 
     73     @Mock IpConnectivityLog mLog;
     74 
     75     @Override
     76     public void setUp() throws Exception {
     77         super.setUp();
     78         MockitoAnnotations.initMocks(this);
     79         // Load up native shared library containing APF interpreter exposed via JNI.
     80         System.loadLibrary("frameworksnettestsjni");
     81     }
     82 
     83     // Expected return codes from APF interpreter.
     84     private final static int PASS = 1;
     85     private final static int DROP = 0;
     86     // Interpreter will just accept packets without link layer headers, so pad fake packet to at
     87     // least the minimum packet size.
     88     private final static int MIN_PKT_SIZE = 15;
     89 
     90     private final static boolean DROP_MULTICAST = true;
     91     private final static boolean ALLOW_MULTICAST = false;
     92 
     93     private static String label(int code) {
     94         switch (code) {
     95             case PASS: return "PASS";
     96             case DROP: return "DROP";
     97             default:   return "UNKNOWN";
     98         }
     99     }
    100 
    101     private static void assertReturnCodesEqual(int expected, int got) {
    102         assertEquals(label(expected), label(got));
    103     }
    104 
    105     private void assertVerdict(int expected, byte[] program, byte[] packet, int filterAge) {
    106         assertReturnCodesEqual(expected, apfSimulate(program, packet, filterAge));
    107     }
    108 
    109     private void assertVerdict(int expected, byte[] program, byte[] packet) {
    110         assertReturnCodesEqual(expected, apfSimulate(program, packet, 0));
    111     }
    112 
    113     private void assertPass(byte[] program, byte[] packet, int filterAge) {
    114         assertVerdict(PASS, program, packet, filterAge);
    115     }
    116 
    117     private void assertPass(byte[] program, byte[] packet) {
    118         assertVerdict(PASS, program, packet);
    119     }
    120 
    121     private void assertDrop(byte[] program, byte[] packet, int filterAge) {
    122         assertVerdict(DROP, program, packet, filterAge);
    123     }
    124 
    125     private void assertDrop(byte[] program, byte[] packet) {
    126         assertVerdict(DROP, program, packet);
    127     }
    128 
    129     private void assertVerdict(int expected, ApfGenerator gen, byte[] packet, int filterAge)
    130             throws IllegalInstructionException {
    131         assertReturnCodesEqual(expected, apfSimulate(gen.generate(), packet, filterAge));
    132     }
    133 
    134     private void assertPass(ApfGenerator gen, byte[] packet, int filterAge)
    135             throws IllegalInstructionException {
    136         assertVerdict(PASS, gen, packet, filterAge);
    137     }
    138 
    139     private void assertDrop(ApfGenerator gen, byte[] packet, int filterAge)
    140             throws IllegalInstructionException {
    141         assertVerdict(DROP, gen, packet, filterAge);
    142     }
    143 
    144     private void assertPass(ApfGenerator gen)
    145             throws IllegalInstructionException {
    146         assertVerdict(PASS, gen, new byte[MIN_PKT_SIZE], 0);
    147     }
    148 
    149     private void assertDrop(ApfGenerator gen)
    150             throws IllegalInstructionException {
    151         assertVerdict(DROP, gen, new byte[MIN_PKT_SIZE], 0);
    152     }
    153 
    154     /**
    155      * Test each instruction by generating a program containing the instruction,
    156      * generating bytecode for that program and running it through the
    157      * interpreter to verify it functions correctly.
    158      */
    159     @SmallTest
    160     public void testApfInstructions() throws IllegalInstructionException {
    161         // Empty program should pass because having the program counter reach the
    162         // location immediately after the program indicates the packet should be
    163         // passed to the AP.
    164         ApfGenerator gen = new ApfGenerator();
    165         assertPass(gen);
    166 
    167         // Test jumping to pass label.
    168         gen = new ApfGenerator();
    169         gen.addJump(gen.PASS_LABEL);
    170         byte[] program = gen.generate();
    171         assertEquals(1, program.length);
    172         assertEquals((14 << 3) | (0 << 1) | 0, program[0]);
    173         assertPass(program, new byte[MIN_PKT_SIZE], 0);
    174 
    175         // Test jumping to drop label.
    176         gen = new ApfGenerator();
    177         gen.addJump(gen.DROP_LABEL);
    178         program = gen.generate();
    179         assertEquals(2, program.length);
    180         assertEquals((14 << 3) | (1 << 1) | 0, program[0]);
    181         assertEquals(1, program[1]);
    182         assertDrop(program, new byte[15], 15);
    183 
    184         // Test jumping if equal to 0.
    185         gen = new ApfGenerator();
    186         gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
    187         assertDrop(gen);
    188 
    189         // Test jumping if not equal to 0.
    190         gen = new ApfGenerator();
    191         gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL);
    192         assertPass(gen);
    193         gen = new ApfGenerator();
    194         gen.addLoadImmediate(Register.R0, 1);
    195         gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL);
    196         assertDrop(gen);
    197 
    198         // Test jumping if registers equal.
    199         gen = new ApfGenerator();
    200         gen.addJumpIfR0EqualsR1(gen.DROP_LABEL);
    201         assertDrop(gen);
    202 
    203         // Test jumping if registers not equal.
    204         gen = new ApfGenerator();
    205         gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL);
    206         assertPass(gen);
    207         gen = new ApfGenerator();
    208         gen.addLoadImmediate(Register.R0, 1);
    209         gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL);
    210         assertDrop(gen);
    211 
    212         // Test load immediate.
    213         gen = new ApfGenerator();
    214         gen.addLoadImmediate(Register.R0, 1234567890);
    215         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
    216         assertDrop(gen);
    217 
    218         // Test add.
    219         gen = new ApfGenerator();
    220         gen.addAdd(1234567890);
    221         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
    222         assertDrop(gen);
    223 
    224         // Test subtract.
    225         gen = new ApfGenerator();
    226         gen.addAdd(-1234567890);
    227         gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
    228         assertDrop(gen);
    229 
    230         // Test or.
    231         gen = new ApfGenerator();
    232         gen.addOr(1234567890);
    233         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
    234         assertDrop(gen);
    235 
    236         // Test and.
    237         gen = new ApfGenerator();
    238         gen.addLoadImmediate(Register.R0, 1234567890);
    239         gen.addAnd(123456789);
    240         gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL);
    241         assertDrop(gen);
    242 
    243         // Test left shift.
    244         gen = new ApfGenerator();
    245         gen.addLoadImmediate(Register.R0, 1234567890);
    246         gen.addLeftShift(1);
    247         gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL);
    248         assertDrop(gen);
    249 
    250         // Test right shift.
    251         gen = new ApfGenerator();
    252         gen.addLoadImmediate(Register.R0, 1234567890);
    253         gen.addRightShift(1);
    254         gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL);
    255         assertDrop(gen);
    256 
    257         // Test multiply.
    258         gen = new ApfGenerator();
    259         gen.addLoadImmediate(Register.R0, 1234567890);
    260         gen.addMul(2);
    261         gen.addJumpIfR0Equals(1234567890 * 2, gen.DROP_LABEL);
    262         assertDrop(gen);
    263 
    264         // Test divide.
    265         gen = new ApfGenerator();
    266         gen.addLoadImmediate(Register.R0, 1234567890);
    267         gen.addDiv(2);
    268         gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL);
    269         assertDrop(gen);
    270 
    271         // Test divide by zero.
    272         gen = new ApfGenerator();
    273         gen.addDiv(0);
    274         gen.addJump(gen.DROP_LABEL);
    275         assertPass(gen);
    276 
    277         // Test add.
    278         gen = new ApfGenerator();
    279         gen.addLoadImmediate(Register.R1, 1234567890);
    280         gen.addAddR1();
    281         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
    282         assertDrop(gen);
    283 
    284         // Test subtract.
    285         gen = new ApfGenerator();
    286         gen.addLoadImmediate(Register.R1, -1234567890);
    287         gen.addAddR1();
    288         gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
    289         assertDrop(gen);
    290 
    291         // Test or.
    292         gen = new ApfGenerator();
    293         gen.addLoadImmediate(Register.R1, 1234567890);
    294         gen.addOrR1();
    295         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
    296         assertDrop(gen);
    297 
    298         // Test and.
    299         gen = new ApfGenerator();
    300         gen.addLoadImmediate(Register.R0, 1234567890);
    301         gen.addLoadImmediate(Register.R1, 123456789);
    302         gen.addAndR1();
    303         gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL);
    304         assertDrop(gen);
    305 
    306         // Test left shift.
    307         gen = new ApfGenerator();
    308         gen.addLoadImmediate(Register.R0, 1234567890);
    309         gen.addLoadImmediate(Register.R1, 1);
    310         gen.addLeftShiftR1();
    311         gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL);
    312         assertDrop(gen);
    313 
    314         // Test right shift.
    315         gen = new ApfGenerator();
    316         gen.addLoadImmediate(Register.R0, 1234567890);
    317         gen.addLoadImmediate(Register.R1, -1);
    318         gen.addLeftShiftR1();
    319         gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL);
    320         assertDrop(gen);
    321 
    322         // Test multiply.
    323         gen = new ApfGenerator();
    324         gen.addLoadImmediate(Register.R0, 1234567890);
    325         gen.addLoadImmediate(Register.R1, 2);
    326         gen.addMulR1();
    327         gen.addJumpIfR0Equals(1234567890 * 2, gen.DROP_LABEL);
    328         assertDrop(gen);
    329 
    330         // Test divide.
    331         gen = new ApfGenerator();
    332         gen.addLoadImmediate(Register.R0, 1234567890);
    333         gen.addLoadImmediate(Register.R1, 2);
    334         gen.addDivR1();
    335         gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL);
    336         assertDrop(gen);
    337 
    338         // Test divide by zero.
    339         gen = new ApfGenerator();
    340         gen.addDivR1();
    341         gen.addJump(gen.DROP_LABEL);
    342         assertPass(gen);
    343 
    344         // Test byte load.
    345         gen = new ApfGenerator();
    346         gen.addLoad8(Register.R0, 1);
    347         gen.addJumpIfR0Equals(45, gen.DROP_LABEL);
    348         assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
    349 
    350         // Test out of bounds load.
    351         gen = new ApfGenerator();
    352         gen.addLoad8(Register.R0, 16);
    353         gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
    354         assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
    355 
    356         // Test half-word load.
    357         gen = new ApfGenerator();
    358         gen.addLoad16(Register.R0, 1);
    359         gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL);
    360         assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
    361 
    362         // Test word load.
    363         gen = new ApfGenerator();
    364         gen.addLoad32(Register.R0, 1);
    365         gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL);
    366         assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0);
    367 
    368         // Test byte indexed load.
    369         gen = new ApfGenerator();
    370         gen.addLoadImmediate(Register.R1, 1);
    371         gen.addLoad8Indexed(Register.R0, 0);
    372         gen.addJumpIfR0Equals(45, gen.DROP_LABEL);
    373         assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
    374 
    375         // Test out of bounds indexed load.
    376         gen = new ApfGenerator();
    377         gen.addLoadImmediate(Register.R1, 8);
    378         gen.addLoad8Indexed(Register.R0, 8);
    379         gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
    380         assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
    381 
    382         // Test half-word indexed load.
    383         gen = new ApfGenerator();
    384         gen.addLoadImmediate(Register.R1, 1);
    385         gen.addLoad16Indexed(Register.R0, 0);
    386         gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL);
    387         assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
    388 
    389         // Test word indexed load.
    390         gen = new ApfGenerator();
    391         gen.addLoadImmediate(Register.R1, 1);
    392         gen.addLoad32Indexed(Register.R0, 0);
    393         gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL);
    394         assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0);
    395 
    396         // Test jumping if greater than.
    397         gen = new ApfGenerator();
    398         gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL);
    399         assertPass(gen);
    400         gen = new ApfGenerator();
    401         gen.addLoadImmediate(Register.R0, 1);
    402         gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL);
    403         assertDrop(gen);
    404 
    405         // Test jumping if less than.
    406         gen = new ApfGenerator();
    407         gen.addJumpIfR0LessThan(0, gen.DROP_LABEL);
    408         assertPass(gen);
    409         gen = new ApfGenerator();
    410         gen.addJumpIfR0LessThan(1, gen.DROP_LABEL);
    411         assertDrop(gen);
    412 
    413         // Test jumping if any bits set.
    414         gen = new ApfGenerator();
    415         gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
    416         assertPass(gen);
    417         gen = new ApfGenerator();
    418         gen.addLoadImmediate(Register.R0, 1);
    419         gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
    420         assertDrop(gen);
    421         gen = new ApfGenerator();
    422         gen.addLoadImmediate(Register.R0, 3);
    423         gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
    424         assertDrop(gen);
    425 
    426         // Test jumping if register greater than.
    427         gen = new ApfGenerator();
    428         gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL);
    429         assertPass(gen);
    430         gen = new ApfGenerator();
    431         gen.addLoadImmediate(Register.R0, 2);
    432         gen.addLoadImmediate(Register.R1, 1);
    433         gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL);
    434         assertDrop(gen);
    435 
    436         // Test jumping if register less than.
    437         gen = new ApfGenerator();
    438         gen.addJumpIfR0LessThanR1(gen.DROP_LABEL);
    439         assertPass(gen);
    440         gen = new ApfGenerator();
    441         gen.addLoadImmediate(Register.R1, 1);
    442         gen.addJumpIfR0LessThanR1(gen.DROP_LABEL);
    443         assertDrop(gen);
    444 
    445         // Test jumping if any bits set in register.
    446         gen = new ApfGenerator();
    447         gen.addLoadImmediate(Register.R1, 3);
    448         gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
    449         assertPass(gen);
    450         gen = new ApfGenerator();
    451         gen.addLoadImmediate(Register.R1, 3);
    452         gen.addLoadImmediate(Register.R0, 1);
    453         gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
    454         assertDrop(gen);
    455         gen = new ApfGenerator();
    456         gen.addLoadImmediate(Register.R1, 3);
    457         gen.addLoadImmediate(Register.R0, 3);
    458         gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
    459         assertDrop(gen);
    460 
    461         // Test load from memory.
    462         gen = new ApfGenerator();
    463         gen.addLoadFromMemory(Register.R0, 0);
    464         gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
    465         assertDrop(gen);
    466 
    467         // Test store to memory.
    468         gen = new ApfGenerator();
    469         gen.addLoadImmediate(Register.R1, 1234567890);
    470         gen.addStoreToMemory(Register.R1, 12);
    471         gen.addLoadFromMemory(Register.R0, 12);
    472         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
    473         assertDrop(gen);
    474 
    475         // Test filter age pre-filled memory.
    476         gen = new ApfGenerator();
    477         gen.addLoadFromMemory(Register.R0, gen.FILTER_AGE_MEMORY_SLOT);
    478         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
    479         assertDrop(gen, new byte[MIN_PKT_SIZE], 1234567890);
    480 
    481         // Test packet size pre-filled memory.
    482         gen = new ApfGenerator();
    483         gen.addLoadFromMemory(Register.R0, gen.PACKET_SIZE_MEMORY_SLOT);
    484         gen.addJumpIfR0Equals(MIN_PKT_SIZE, gen.DROP_LABEL);
    485         assertDrop(gen);
    486 
    487         // Test IPv4 header size pre-filled memory.
    488         gen = new ApfGenerator();
    489         gen.addLoadFromMemory(Register.R0, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
    490         gen.addJumpIfR0Equals(20, gen.DROP_LABEL);
    491         assertDrop(gen, new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x45}, 0);
    492 
    493         // Test not.
    494         gen = new ApfGenerator();
    495         gen.addLoadImmediate(Register.R0, 1234567890);
    496         gen.addNot(Register.R0);
    497         gen.addJumpIfR0Equals(~1234567890, gen.DROP_LABEL);
    498         assertDrop(gen);
    499 
    500         // Test negate.
    501         gen = new ApfGenerator();
    502         gen.addLoadImmediate(Register.R0, 1234567890);
    503         gen.addNeg(Register.R0);
    504         gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
    505         assertDrop(gen);
    506 
    507         // Test move.
    508         gen = new ApfGenerator();
    509         gen.addLoadImmediate(Register.R1, 1234567890);
    510         gen.addMove(Register.R0);
    511         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
    512         assertDrop(gen);
    513         gen = new ApfGenerator();
    514         gen.addLoadImmediate(Register.R0, 1234567890);
    515         gen.addMove(Register.R1);
    516         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
    517         assertDrop(gen);
    518 
    519         // Test swap.
    520         gen = new ApfGenerator();
    521         gen.addLoadImmediate(Register.R1, 1234567890);
    522         gen.addSwap();
    523         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
    524         assertDrop(gen);
    525         gen = new ApfGenerator();
    526         gen.addLoadImmediate(Register.R0, 1234567890);
    527         gen.addSwap();
    528         gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
    529         assertDrop(gen);
    530 
    531         // Test jump if bytes not equal.
    532         gen = new ApfGenerator();
    533         gen.addLoadImmediate(Register.R0, 1);
    534         gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
    535         program = gen.generate();
    536         assertEquals(6, program.length);
    537         assertEquals((13 << 3) | (1 << 1) | 0, program[0]);
    538         assertEquals(1, program[1]);
    539         assertEquals(((20 << 3) | (1 << 1) | 0) - 256, program[2]);
    540         assertEquals(1, program[3]);
    541         assertEquals(1, program[4]);
    542         assertEquals(123, program[5]);
    543         assertDrop(program, new byte[MIN_PKT_SIZE], 0);
    544         gen = new ApfGenerator();
    545         gen.addLoadImmediate(Register.R0, 1);
    546         gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
    547         byte[] packet123 = {0,123,0,0,0,0,0,0,0,0,0,0,0,0,0};
    548         assertPass(gen, packet123, 0);
    549         gen = new ApfGenerator();
    550         gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
    551         assertDrop(gen, packet123, 0);
    552         gen = new ApfGenerator();
    553         gen.addLoadImmediate(Register.R0, 1);
    554         gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,30,4,5}, gen.DROP_LABEL);
    555         byte[] packet12345 = {0,1,2,3,4,5,0,0,0,0,0,0,0,0,0};
    556         assertDrop(gen, packet12345, 0);
    557         gen = new ApfGenerator();
    558         gen.addLoadImmediate(Register.R0, 1);
    559         gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,3,4,5}, gen.DROP_LABEL);
    560         assertPass(gen, packet12345, 0);
    561     }
    562 
    563     /**
    564      * Generate some BPF programs, translate them to APF, then run APF and BPF programs
    565      * over packet traces and verify both programs filter out the same packets.
    566      */
    567     @SmallTest
    568     public void testApfAgainstBpf() throws Exception {
    569         String[] tcpdump_filters = new String[]{ "udp", "tcp", "icmp", "icmp6", "udp port 53",
    570                 "arp", "dst 239.255.255.250", "arp or tcp or udp port 53", "net 192.168.1.0/24",
    571                 "arp or icmp6 or portrange 53-54", "portrange 53-54 or portrange 100-50000",
    572                 "tcp[tcpflags] & (tcp-ack|tcp-fin) != 0 and (ip[2:2] > 57 or icmp)" };
    573         String pcap_filename = stageFile(R.raw.apf);
    574         for (String tcpdump_filter : tcpdump_filters) {
    575             byte[] apf_program = Bpf2Apf.convert(compileToBpf(tcpdump_filter));
    576             assertTrue("Failed to match for filter: " + tcpdump_filter,
    577                     compareBpfApf(tcpdump_filter, pcap_filename, apf_program));
    578         }
    579     }
    580 
    581     private class MockIpManagerCallback extends IpManager.Callback {
    582         private final ConditionVariable mGotApfProgram = new ConditionVariable();
    583         private byte[] mLastApfProgram;
    584 
    585         @Override
    586         public void installPacketFilter(byte[] filter) {
    587             mLastApfProgram = filter;
    588             mGotApfProgram.open();
    589         }
    590 
    591         public void resetApfProgramWait() {
    592             mGotApfProgram.close();
    593         }
    594 
    595         public byte[] getApfProgram() {
    596             assertTrue(mGotApfProgram.block(TIMEOUT_MS));
    597             return mLastApfProgram;
    598         }
    599 
    600         public void assertNoProgramUpdate() {
    601             assertFalse(mGotApfProgram.block(TIMEOUT_MS));
    602         }
    603     }
    604 
    605     private static class TestApfFilter extends ApfFilter {
    606         public final static byte[] MOCK_MAC_ADDR = {1,2,3,4,5,6};
    607         private FileDescriptor mWriteSocket;
    608 
    609         private final long mFixedTimeMs = SystemClock.elapsedRealtime();
    610 
    611         public TestApfFilter(IpManager.Callback ipManagerCallback, boolean multicastFilter,
    612                 IpConnectivityLog log) throws Exception {
    613             super(new ApfCapabilities(2, 1700, ARPHRD_ETHER), NetworkInterface.getByName("lo"),
    614                     ipManagerCallback, multicastFilter, log);
    615         }
    616 
    617         // Pretend an RA packet has been received and show it to ApfFilter.
    618         public void pretendPacketReceived(byte[] packet) throws IOException, ErrnoException {
    619             // ApfFilter's ReceiveThread will be waiting to read this.
    620             Os.write(mWriteSocket, packet, 0, packet.length);
    621         }
    622 
    623         @Override
    624         protected long currentTimeSeconds() {
    625             return mFixedTimeMs / DateUtils.SECOND_IN_MILLIS;
    626         }
    627 
    628         @Override
    629         void maybeStartFilter() {
    630             mHardwareAddress = MOCK_MAC_ADDR;
    631             installNewProgramLocked();
    632 
    633             // Create two sockets, "readSocket" and "mWriteSocket" and connect them together.
    634             FileDescriptor readSocket = new FileDescriptor();
    635             mWriteSocket = new FileDescriptor();
    636             try {
    637                 Os.socketpair(AF_UNIX, SOCK_STREAM, 0, mWriteSocket, readSocket);
    638             } catch (ErrnoException e) {
    639                 fail();
    640                 return;
    641             }
    642             // Now pass readSocket to ReceiveThread as if it was setup to read raw RAs.
    643             // This allows us to pretend RA packets have been recieved via pretendPacketReceived().
    644             mReceiveThread = new ReceiveThread(readSocket);
    645             mReceiveThread.start();
    646         }
    647 
    648         @Override
    649         public void shutdown() {
    650             super.shutdown();
    651             IoUtils.closeQuietly(mWriteSocket);
    652         }
    653     }
    654 
    655     private static final int ETH_HEADER_LEN = 14;
    656     private static final int ETH_DEST_ADDR_OFFSET = 0;
    657     private static final int ETH_ETHERTYPE_OFFSET = 12;
    658     private static final byte[] ETH_BROADCAST_MAC_ADDRESS =
    659             {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
    660 
    661     private static final int IPV4_VERSION_IHL_OFFSET = ETH_HEADER_LEN + 0;
    662     private static final int IPV4_PROTOCOL_OFFSET = ETH_HEADER_LEN + 9;
    663     private static final int IPV4_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 16;
    664     private static final byte[] IPV4_BROADCAST_ADDRESS =
    665             {(byte) 255, (byte) 255, (byte) 255, (byte) 255};
    666 
    667     private static final int IPV6_NEXT_HEADER_OFFSET = ETH_HEADER_LEN + 6;
    668     private static final int IPV6_HEADER_LEN = 40;
    669     private static final int IPV6_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 24;
    670     // The IPv6 all nodes address ff02::1
    671     private static final byte[] IPV6_ALL_NODES_ADDRESS =
    672             { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
    673     private static final byte[] IPV6_ALL_ROUTERS_ADDRESS =
    674             { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 };
    675 
    676     private static final int ICMP6_TYPE_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN;
    677     private static final int ICMP6_ROUTER_SOLICITATION = 133;
    678     private static final int ICMP6_ROUTER_ADVERTISEMENT = 134;
    679     private static final int ICMP6_NEIGHBOR_SOLICITATION = 135;
    680     private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136;
    681 
    682     private static final int ICMP6_RA_HEADER_LEN = 16;
    683     private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET =
    684             ETH_HEADER_LEN + IPV6_HEADER_LEN + 6;
    685     private static final int ICMP6_RA_CHECKSUM_OFFSET =
    686             ETH_HEADER_LEN + IPV6_HEADER_LEN + 2;
    687     private static final int ICMP6_RA_OPTION_OFFSET =
    688             ETH_HEADER_LEN + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN;
    689 
    690     private static final int ICMP6_PREFIX_OPTION_TYPE = 3;
    691     private static final int ICMP6_PREFIX_OPTION_LEN = 32;
    692     private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET = 4;
    693     private static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET = 8;
    694 
    695     // From RFC6106: Recursive DNS Server option
    696     private static final int ICMP6_RDNSS_OPTION_TYPE = 25;
    697     // From RFC6106: DNS Search List option
    698     private static final int ICMP6_DNSSL_OPTION_TYPE = 31;
    699 
    700     // From RFC4191: Route Information option
    701     private static final int ICMP6_ROUTE_INFO_OPTION_TYPE = 24;
    702     // Above three options all have the same format:
    703     private static final int ICMP6_4_BYTE_OPTION_LEN = 8;
    704     private static final int ICMP6_4_BYTE_LIFETIME_OFFSET = 4;
    705     private static final int ICMP6_4_BYTE_LIFETIME_LEN = 4;
    706 
    707     private static final int UDP_HEADER_LEN = 8;
    708     private static final int UDP_DESTINATION_PORT_OFFSET = ETH_HEADER_LEN + 22;
    709 
    710     private static final int DHCP_CLIENT_PORT = 68;
    711     private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 48;
    712 
    713     private static final int ARP_HEADER_OFFSET = ETH_HEADER_LEN;
    714     private static final byte[] ARP_IPV4_REQUEST_HEADER = {
    715             0, 1, // Hardware type: Ethernet (1)
    716             8, 0, // Protocol type: IP (0x0800)
    717             6,    // Hardware size: 6
    718             4,    // Protocol size: 4
    719             0, 1  // Opcode: request (1)
    720     };
    721     private static final byte[] ARP_IPV4_REPLY_HEADER = {
    722             0, 1, // Hardware type: Ethernet (1)
    723             8, 0, // Protocol type: IP (0x0800)
    724             6,    // Hardware size: 6
    725             4,    // Protocol size: 4
    726             0, 2  // Opcode: reply (2)
    727     };
    728     private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ETH_HEADER_LEN + 24;
    729 
    730     private static final byte[] MOCK_IPV4_ADDR           = {10, 0, 0, 1};
    731     private static final byte[] MOCK_BROADCAST_IPV4_ADDR = {10, 0, 31, (byte) 255}; // prefix = 19
    732     private static final byte[] MOCK_MULTICAST_IPV4_ADDR = {(byte) 224, 0, 0, 1};
    733     private static final byte[] ANOTHER_IPV4_ADDR        = {10, 0, 0, 2};
    734     private static final byte[] IPV4_ANY_HOST_ADDR       = {0, 0, 0, 0};
    735 
    736     @SmallTest
    737     public void testApfFilterIPv4() throws Exception {
    738         MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
    739         LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
    740         LinkProperties lp = new LinkProperties();
    741         lp.addLinkAddress(link);
    742 
    743         ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, mLog);
    744         apfFilter.setLinkProperties(lp);
    745 
    746         byte[] program = ipManagerCallback.getApfProgram();
    747 
    748         // Verify empty packet of 100 zero bytes is passed
    749         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
    750         assertPass(program, packet.array());
    751 
    752         // Verify unicast IPv4 packet is passed
    753         put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
    754         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
    755         put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_IPV4_ADDR);
    756         assertPass(program, packet.array());
    757 
    758         // Verify L2 unicast to IPv4 broadcast addresses is dropped (b/30231088)
    759         put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
    760         assertDrop(program, packet.array());
    761         put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR);
    762         assertDrop(program, packet.array());
    763 
    764         // Verify multicast/broadcast IPv4, not DHCP to us, is dropped
    765         put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
    766         assertDrop(program, packet.array());
    767         packet.put(IPV4_VERSION_IHL_OFFSET, (byte)0x45);
    768         assertDrop(program, packet.array());
    769         packet.put(IPV4_PROTOCOL_OFFSET, (byte)IPPROTO_UDP);
    770         assertDrop(program, packet.array());
    771         packet.putShort(UDP_DESTINATION_PORT_OFFSET, (short)DHCP_CLIENT_PORT);
    772         assertDrop(program, packet.array());
    773         put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_MULTICAST_IPV4_ADDR);
    774         assertDrop(program, packet.array());
    775         put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR);
    776         assertDrop(program, packet.array());
    777         put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
    778         assertDrop(program, packet.array());
    779 
    780         // Verify broadcast IPv4 DHCP to us is passed
    781         put(packet, DHCP_CLIENT_MAC_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
    782         assertPass(program, packet.array());
    783 
    784         // Verify unicast IPv4 DHCP to us is passed
    785         put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
    786         assertPass(program, packet.array());
    787 
    788         apfFilter.shutdown();
    789     }
    790 
    791     @SmallTest
    792     public void testApfFilterIPv6() throws Exception {
    793         MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
    794         ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog);
    795         byte[] program = ipManagerCallback.getApfProgram();
    796 
    797         // Verify empty IPv6 packet is passed
    798         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
    799         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
    800         assertPass(program, packet.array());
    801 
    802         // Verify empty ICMPv6 packet is passed
    803         packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
    804         assertPass(program, packet.array());
    805 
    806         // Verify empty ICMPv6 NA packet is passed
    807         packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_NEIGHBOR_ANNOUNCEMENT);
    808         assertPass(program, packet.array());
    809 
    810         // Verify ICMPv6 NA to ff02::1 is dropped
    811         put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_NODES_ADDRESS);
    812         assertDrop(program, packet.array());
    813 
    814         // Verify ICMPv6 RS to any is dropped
    815         packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_SOLICITATION);
    816         assertDrop(program, packet.array());
    817         put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_ROUTERS_ADDRESS);
    818         assertDrop(program, packet.array());
    819 
    820         apfFilter.shutdown();
    821     }
    822 
    823     @SmallTest
    824     public void testApfFilterMulticast() throws Exception {
    825         final byte[] unicastIpv4Addr   = {(byte)192,0,2,63};
    826         final byte[] broadcastIpv4Addr = {(byte)192,0,2,(byte)255};
    827         final byte[] multicastIpv4Addr = {(byte)224,0,0,1};
    828         final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb};
    829 
    830         MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
    831         LinkAddress link = new LinkAddress(InetAddress.getByAddress(unicastIpv4Addr), 24);
    832         LinkProperties lp = new LinkProperties();
    833         lp.addLinkAddress(link);
    834 
    835         ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog);
    836         apfFilter.setLinkProperties(lp);
    837 
    838         byte[] program = ipManagerCallback.getApfProgram();
    839 
    840         // Construct IPv4 and IPv6 multicast packets.
    841         ByteBuffer mcastv4packet = ByteBuffer.wrap(new byte[100]);
    842         mcastv4packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
    843         put(mcastv4packet, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr);
    844 
    845         ByteBuffer mcastv6packet = ByteBuffer.wrap(new byte[100]);
    846         mcastv6packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
    847         mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_UDP);
    848         put(mcastv6packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr);
    849 
    850         // Construct IPv4 broadcast packet.
    851         ByteBuffer bcastv4packet1 = ByteBuffer.wrap(new byte[100]);
    852         bcastv4packet1.put(ETH_BROADCAST_MAC_ADDRESS);
    853         bcastv4packet1.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
    854         put(bcastv4packet1, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr);
    855 
    856         ByteBuffer bcastv4packet2 = ByteBuffer.wrap(new byte[100]);
    857         bcastv4packet2.put(ETH_BROADCAST_MAC_ADDRESS);
    858         bcastv4packet2.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
    859         put(bcastv4packet2, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
    860 
    861         // Construct IPv4 broadcast with L2 unicast address packet (b/30231088).
    862         ByteBuffer bcastv4unicastl2packet = ByteBuffer.wrap(new byte[100]);
    863         bcastv4unicastl2packet.put(TestApfFilter.MOCK_MAC_ADDR);
    864         bcastv4unicastl2packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
    865         put(bcastv4unicastl2packet, IPV4_DEST_ADDR_OFFSET, broadcastIpv4Addr);
    866 
    867         // Verify initially disabled multicast filter is off
    868         assertPass(program, mcastv4packet.array());
    869         assertPass(program, mcastv6packet.array());
    870         assertPass(program, bcastv4packet1.array());
    871         assertPass(program, bcastv4packet2.array());
    872         assertPass(program, bcastv4unicastl2packet.array());
    873 
    874         // Turn on multicast filter and verify it works
    875         ipManagerCallback.resetApfProgramWait();
    876         apfFilter.setMulticastFilter(true);
    877         program = ipManagerCallback.getApfProgram();
    878         assertDrop(program, mcastv4packet.array());
    879         assertDrop(program, mcastv6packet.array());
    880         assertDrop(program, bcastv4packet1.array());
    881         assertDrop(program, bcastv4packet2.array());
    882         assertDrop(program, bcastv4unicastl2packet.array());
    883 
    884         // Turn off multicast filter and verify it's off
    885         ipManagerCallback.resetApfProgramWait();
    886         apfFilter.setMulticastFilter(false);
    887         program = ipManagerCallback.getApfProgram();
    888         assertPass(program, mcastv4packet.array());
    889         assertPass(program, mcastv6packet.array());
    890         assertPass(program, bcastv4packet1.array());
    891         assertPass(program, bcastv4packet2.array());
    892         assertPass(program, bcastv4unicastl2packet.array());
    893 
    894         // Verify it can be initialized to on
    895         ipManagerCallback.resetApfProgramWait();
    896         apfFilter.shutdown();
    897         apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, mLog);
    898         apfFilter.setLinkProperties(lp);
    899         program = ipManagerCallback.getApfProgram();
    900         assertDrop(program, mcastv4packet.array());
    901         assertDrop(program, mcastv6packet.array());
    902         assertDrop(program, bcastv4packet1.array());
    903         assertDrop(program, bcastv4unicastl2packet.array());
    904 
    905         // Verify that ICMPv6 multicast is not dropped.
    906         mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
    907         assertPass(program, mcastv6packet.array());
    908 
    909         apfFilter.shutdown();
    910     }
    911 
    912     private byte[] getProgram(MockIpManagerCallback cb, ApfFilter filter, LinkProperties lp) {
    913         cb.resetApfProgramWait();
    914         filter.setLinkProperties(lp);
    915         return cb.getApfProgram();
    916     }
    917 
    918     private void verifyArpFilter(byte[] program, int filterResult) {
    919         // Verify ARP request packet
    920         assertPass(program, arpRequestBroadcast(MOCK_IPV4_ADDR));
    921         assertVerdict(filterResult, program, arpRequestBroadcast(ANOTHER_IPV4_ADDR));
    922         assertDrop(program, arpRequestBroadcast(IPV4_ANY_HOST_ADDR));
    923 
    924         // Verify unicast ARP reply packet is always accepted.
    925         assertPass(program, arpReplyUnicast(MOCK_IPV4_ADDR));
    926         assertPass(program, arpReplyUnicast(ANOTHER_IPV4_ADDR));
    927         assertPass(program, arpReplyUnicast(IPV4_ANY_HOST_ADDR));
    928 
    929         // Verify GARP reply packets are always filtered
    930         assertDrop(program, garpReply());
    931     }
    932 
    933     @SmallTest
    934     public void testApfFilterArp() throws Exception {
    935         MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
    936         ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog);
    937 
    938         // Verify initially ARP request filter is off, and GARP filter is on.
    939         verifyArpFilter(ipManagerCallback.getApfProgram(), PASS);
    940 
    941         // Inform ApfFilter of our address and verify ARP filtering is on
    942         LinkAddress linkAddress = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 24);
    943         LinkProperties lp = new LinkProperties();
    944         assertTrue(lp.addLinkAddress(linkAddress));
    945         verifyArpFilter(getProgram(ipManagerCallback, apfFilter, lp), DROP);
    946 
    947         // Inform ApfFilter of loss of IP and verify ARP filtering is off
    948         verifyArpFilter(getProgram(ipManagerCallback, apfFilter, new LinkProperties()), PASS);
    949 
    950         apfFilter.shutdown();
    951     }
    952 
    953     private static byte[] arpRequestBroadcast(byte[] tip) {
    954         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
    955         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
    956         put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
    957         put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
    958         put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip);
    959         return packet.array();
    960     }
    961 
    962     private static byte[] arpReplyUnicast(byte[] tip) {
    963         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
    964         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
    965         put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
    966         put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip);
    967         return packet.array();
    968     }
    969 
    970     private static byte[] garpReply() {
    971         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
    972         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
    973         put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
    974         put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
    975         put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, IPV4_ANY_HOST_ADDR);
    976         return packet.array();
    977     }
    978 
    979     // Verify that the last program pushed to the IpManager.Callback properly filters the
    980     // given packet for the given lifetime.
    981     private void verifyRaLifetime(byte[] program, ByteBuffer packet, int lifetime) {
    982         final int FRACTION_OF_LIFETIME = 6;
    983         final int ageLimit = lifetime / FRACTION_OF_LIFETIME;
    984 
    985         // Verify new program should drop RA for 1/6th its lifetime and pass afterwards.
    986         assertDrop(program, packet.array());
    987         assertDrop(program, packet.array(), ageLimit);
    988         assertPass(program, packet.array(), ageLimit + 1);
    989         assertPass(program, packet.array(), lifetime);
    990         // Verify RA checksum is ignored
    991         final short originalChecksum = packet.getShort(ICMP6_RA_CHECKSUM_OFFSET);
    992         packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)12345);
    993         assertDrop(program, packet.array());
    994         packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)-12345);
    995         assertDrop(program, packet.array());
    996         packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, originalChecksum);
    997 
    998         // Verify other changes to RA make it not match filter
    999         final byte originalFirstByte = packet.get(0);
   1000         packet.put(0, (byte)-1);
   1001         assertPass(program, packet.array());
   1002         packet.put(0, (byte)0);
   1003         assertDrop(program, packet.array());
   1004         packet.put(0, originalFirstByte);
   1005     }
   1006 
   1007     // Test that when ApfFilter is shown the given packet, it generates a program to filter it
   1008     // for the given lifetime.
   1009     private void testRaLifetime(TestApfFilter apfFilter, MockIpManagerCallback ipManagerCallback,
   1010             ByteBuffer packet, int lifetime) throws IOException, ErrnoException {
   1011         // Verify new program generated if ApfFilter witnesses RA
   1012         ipManagerCallback.resetApfProgramWait();
   1013         apfFilter.pretendPacketReceived(packet.array());
   1014         byte[] program = ipManagerCallback.getApfProgram();
   1015         verifyRaLifetime(program, packet, lifetime);
   1016     }
   1017 
   1018     private void verifyRaEvent(RaEvent expected) {
   1019         ArgumentCaptor<Parcelable> captor = ArgumentCaptor.forClass(Parcelable.class);
   1020         verify(mLog, atLeastOnce()).log(captor.capture());
   1021         RaEvent got = lastRaEvent(captor.getAllValues());
   1022         if (!raEventEquals(expected, got)) {
   1023             assertEquals(expected, got);  // fail for printing an assertion error message.
   1024         }
   1025     }
   1026 
   1027     private RaEvent lastRaEvent(List<Parcelable> events) {
   1028         RaEvent got = null;
   1029         for (Parcelable ev : events) {
   1030             if (ev instanceof RaEvent) {
   1031                 got = (RaEvent) ev;
   1032             }
   1033         }
   1034         return got;
   1035     }
   1036 
   1037     private boolean raEventEquals(RaEvent ev1, RaEvent ev2) {
   1038         return (ev1 != null) && (ev2 != null)
   1039                 && (ev1.routerLifetime == ev2.routerLifetime)
   1040                 && (ev1.prefixValidLifetime == ev2.prefixValidLifetime)
   1041                 && (ev1.prefixPreferredLifetime == ev2.prefixPreferredLifetime)
   1042                 && (ev1.routeInfoLifetime == ev2.routeInfoLifetime)
   1043                 && (ev1.rdnssLifetime == ev2.rdnssLifetime)
   1044                 && (ev1.dnsslLifetime == ev2.dnsslLifetime);
   1045     }
   1046 
   1047     private void assertInvalidRa(TestApfFilter apfFilter, MockIpManagerCallback ipManagerCallback,
   1048             ByteBuffer packet) throws IOException, ErrnoException {
   1049         ipManagerCallback.resetApfProgramWait();
   1050         apfFilter.pretendPacketReceived(packet.array());
   1051         ipManagerCallback.assertNoProgramUpdate();
   1052     }
   1053 
   1054     @SmallTest
   1055     public void testApfFilterRa() throws Exception {
   1056         MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
   1057         TestApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, mLog);
   1058         byte[] program = ipManagerCallback.getApfProgram();
   1059 
   1060         final int ROUTER_LIFETIME = 1000;
   1061         final int PREFIX_VALID_LIFETIME = 200;
   1062         final int PREFIX_PREFERRED_LIFETIME = 100;
   1063         final int RDNSS_LIFETIME  = 300;
   1064         final int ROUTE_LIFETIME  = 400;
   1065         // Note that lifetime of 2000 will be ignored in favor of shorter route lifetime of 1000.
   1066         final int DNSSL_LIFETIME  = 2000;
   1067 
   1068         // Verify RA is passed the first time
   1069         ByteBuffer basePacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]);
   1070         basePacket.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
   1071         basePacket.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
   1072         basePacket.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_ADVERTISEMENT);
   1073         basePacket.putShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET, (short)ROUTER_LIFETIME);
   1074         basePacket.position(IPV6_DEST_ADDR_OFFSET);
   1075         basePacket.put(IPV6_ALL_NODES_ADDRESS);
   1076         assertPass(program, basePacket.array());
   1077 
   1078         testRaLifetime(apfFilter, ipManagerCallback, basePacket, ROUTER_LIFETIME);
   1079         verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, -1));
   1080 
   1081         // Ensure zero-length options cause the packet to be silently skipped.
   1082         // Do this before we test other packets. http://b/29586253
   1083         ByteBuffer zeroLengthOptionPacket = ByteBuffer.wrap(
   1084                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
   1085         basePacket.clear();
   1086         zeroLengthOptionPacket.put(basePacket);
   1087         zeroLengthOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE);
   1088         zeroLengthOptionPacket.put((byte)0);
   1089         assertInvalidRa(apfFilter, ipManagerCallback, zeroLengthOptionPacket);
   1090 
   1091         // Generate several RAs with different options and lifetimes, and verify when
   1092         // ApfFilter is shown these packets, it generates programs to filter them for the
   1093         // appropriate lifetime.
   1094         ByteBuffer prefixOptionPacket = ByteBuffer.wrap(
   1095                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_LEN]);
   1096         basePacket.clear();
   1097         prefixOptionPacket.put(basePacket);
   1098         prefixOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE);
   1099         prefixOptionPacket.put((byte)(ICMP6_PREFIX_OPTION_LEN / 8));
   1100         prefixOptionPacket.putInt(
   1101                 ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET,
   1102                 PREFIX_PREFERRED_LIFETIME);
   1103         prefixOptionPacket.putInt(
   1104                 ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET,
   1105                 PREFIX_VALID_LIFETIME);
   1106         testRaLifetime(apfFilter, ipManagerCallback, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
   1107         verifyRaEvent(new RaEvent(
   1108                 ROUTER_LIFETIME, PREFIX_VALID_LIFETIME, PREFIX_PREFERRED_LIFETIME, -1, -1, -1));
   1109 
   1110         ByteBuffer rdnssOptionPacket = ByteBuffer.wrap(
   1111                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
   1112         basePacket.clear();
   1113         rdnssOptionPacket.put(basePacket);
   1114         rdnssOptionPacket.put((byte)ICMP6_RDNSS_OPTION_TYPE);
   1115         rdnssOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
   1116         rdnssOptionPacket.putInt(
   1117                 ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, RDNSS_LIFETIME);
   1118         testRaLifetime(apfFilter, ipManagerCallback, rdnssOptionPacket, RDNSS_LIFETIME);
   1119         verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, RDNSS_LIFETIME, -1));
   1120 
   1121         ByteBuffer routeInfoOptionPacket = ByteBuffer.wrap(
   1122                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
   1123         basePacket.clear();
   1124         routeInfoOptionPacket.put(basePacket);
   1125         routeInfoOptionPacket.put((byte)ICMP6_ROUTE_INFO_OPTION_TYPE);
   1126         routeInfoOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
   1127         routeInfoOptionPacket.putInt(
   1128                 ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, ROUTE_LIFETIME);
   1129         testRaLifetime(apfFilter, ipManagerCallback, routeInfoOptionPacket, ROUTE_LIFETIME);
   1130         verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, ROUTE_LIFETIME, -1, -1));
   1131 
   1132         ByteBuffer dnsslOptionPacket = ByteBuffer.wrap(
   1133                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
   1134         basePacket.clear();
   1135         dnsslOptionPacket.put(basePacket);
   1136         dnsslOptionPacket.put((byte)ICMP6_DNSSL_OPTION_TYPE);
   1137         dnsslOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
   1138         dnsslOptionPacket.putInt(
   1139                 ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, DNSSL_LIFETIME);
   1140         testRaLifetime(apfFilter, ipManagerCallback, dnsslOptionPacket, ROUTER_LIFETIME);
   1141         verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, DNSSL_LIFETIME));
   1142 
   1143         // Verify that current program filters all five RAs:
   1144         program = ipManagerCallback.getApfProgram();
   1145         verifyRaLifetime(program, basePacket, ROUTER_LIFETIME);
   1146         verifyRaLifetime(program, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
   1147         verifyRaLifetime(program, rdnssOptionPacket, RDNSS_LIFETIME);
   1148         verifyRaLifetime(program, routeInfoOptionPacket, ROUTE_LIFETIME);
   1149         verifyRaLifetime(program, dnsslOptionPacket, ROUTER_LIFETIME);
   1150 
   1151         apfFilter.shutdown();
   1152     }
   1153 
   1154     /**
   1155      * Stage a file for testing, i.e. make it native accessible. Given a resource ID,
   1156      * copy that resource into the app's data directory and return the path to it.
   1157      */
   1158     private String stageFile(int rawId) throws Exception {
   1159         File file = new File(getContext().getFilesDir(), "staged_file");
   1160         new File(file.getParent()).mkdirs();
   1161         InputStream in = null;
   1162         OutputStream out = null;
   1163         try {
   1164             in = getContext().getResources().openRawResource(rawId);
   1165             out = new FileOutputStream(file);
   1166             Streams.copy(in, out);
   1167         } finally {
   1168             if (in != null) in.close();
   1169             if (out != null) out.close();
   1170         }
   1171         return file.getAbsolutePath();
   1172     }
   1173 
   1174     private static void put(ByteBuffer buffer, int position, byte[] bytes) {
   1175         final int original = buffer.position();
   1176         buffer.position(position);
   1177         buffer.put(bytes);
   1178         buffer.position(original);
   1179     }
   1180 
   1181     @SmallTest
   1182     public void testRaParsing() throws Exception {
   1183         final int maxRandomPacketSize = 512;
   1184         final Random r = new Random();
   1185         MockIpManagerCallback cb = new MockIpManagerCallback();
   1186         TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST, mLog);
   1187         for (int i = 0; i < 1000; i++) {
   1188             byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
   1189             r.nextBytes(packet);
   1190             try {
   1191                 apfFilter.new Ra(packet, packet.length);
   1192             } catch (ApfFilter.InvalidRaException e) {
   1193             } catch (Exception e) {
   1194                 throw new Exception("bad packet: " + HexDump.toHexString(packet), e);
   1195             }
   1196         }
   1197     }
   1198 
   1199     @SmallTest
   1200     public void testRaProcessing() throws Exception {
   1201         final int maxRandomPacketSize = 512;
   1202         final Random r = new Random();
   1203         MockIpManagerCallback cb = new MockIpManagerCallback();
   1204         TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST, mLog);
   1205         for (int i = 0; i < 1000; i++) {
   1206             byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
   1207             r.nextBytes(packet);
   1208             try {
   1209                 apfFilter.processRa(packet, packet.length);
   1210             } catch (Exception e) {
   1211                 throw new Exception("bad packet: " + HexDump.toHexString(packet), e);
   1212             }
   1213         }
   1214     }
   1215 
   1216     /**
   1217      * Call the APF interpreter the run {@code program} on {@code packet} pretending the
   1218      * filter was installed {@code filter_age} seconds ago.
   1219      */
   1220     private native static int apfSimulate(byte[] program, byte[] packet, int filter_age);
   1221 
   1222     /**
   1223      * Compile a tcpdump human-readable filter (e.g. "icmp" or "tcp port 54") into a BPF
   1224      * prorgam and return a human-readable dump of the BPF program identical to "tcpdump -d".
   1225      */
   1226     private native static String compileToBpf(String filter);
   1227 
   1228     /**
   1229      * Open packet capture file {@code pcap_filename} and filter the packets using tcpdump
   1230      * human-readable filter (e.g. "icmp" or "tcp port 54") compiled to a BPF program and
   1231      * at the same time using APF program {@code apf_program}.  Return {@code true} if
   1232      * both APF and BPF programs filter out exactly the same packets.
   1233      */
   1234     private native static boolean compareBpfApf(String filter, String pcap_filename,
   1235             byte[] apf_program);
   1236 
   1237     @SmallTest
   1238     public void testBytesToInt() {
   1239         assertEquals(0x00000000, ApfFilter.bytesToInt(IPV4_ANY_HOST_ADDR));
   1240         assertEquals(0xffffffff, ApfFilter.bytesToInt(IPV4_BROADCAST_ADDRESS));
   1241         assertEquals(0x0a000001, ApfFilter.bytesToInt(MOCK_IPV4_ADDR));
   1242         assertEquals(0x0a000002, ApfFilter.bytesToInt(ANOTHER_IPV4_ADDR));
   1243         assertEquals(0x0a001fff, ApfFilter.bytesToInt(MOCK_BROADCAST_IPV4_ADDR));
   1244         assertEquals(0xe0000001, ApfFilter.bytesToInt(MOCK_MULTICAST_IPV4_ADDR));
   1245     }
   1246 
   1247     public void testBroadcastAddress() throws Exception {
   1248         assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 0));
   1249         assertEqualsIp("0.0.0.0", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 32));
   1250         assertEqualsIp("0.0.3.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 22));
   1251         assertEqualsIp("0.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 8));
   1252 
   1253         assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 0));
   1254         assertEqualsIp("10.0.0.1", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 32));
   1255         assertEqualsIp("10.0.0.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 24));
   1256         assertEqualsIp("10.0.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 16));
   1257     }
   1258 
   1259     public void assertEqualsIp(String expected, int got) throws Exception {
   1260         int want = ApfFilter.bytesToInt(InetAddress.getByName(expected).getAddress());
   1261         assertEquals(want, got);
   1262     }
   1263 }
   1264