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