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