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