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