• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.net.apf;
18 
19 import static android.net.util.NetworkConstants.*;
20 import static android.system.OsConstants.*;
21 import static com.android.internal.util.BitUtils.bytesToBEInt;
22 import static com.android.internal.util.BitUtils.put;
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertFalse;
25 import static org.junit.Assert.assertTrue;
26 import static org.junit.Assert.fail;
27 import static org.mockito.Mockito.atLeastOnce;
28 import static org.mockito.Mockito.verify;
29 
30 import android.content.Context;
31 import android.net.LinkAddress;
32 import android.net.LinkProperties;
33 import android.net.apf.ApfFilter.ApfConfiguration;
34 import android.net.apf.ApfGenerator.IllegalInstructionException;
35 import android.net.apf.ApfGenerator.Register;
36 import android.net.ip.IpClient;
37 import android.net.metrics.IpConnectivityLog;
38 import android.net.metrics.RaEvent;
39 import android.net.util.InterfaceParams;
40 import android.os.ConditionVariable;
41 import android.os.Parcelable;
42 import android.os.SystemClock;
43 import android.support.test.InstrumentationRegistry;
44 import android.support.test.filters.SmallTest;
45 import android.support.test.runner.AndroidJUnit4;
46 import android.system.ErrnoException;
47 import android.system.Os;
48 import android.text.format.DateUtils;
49 import com.android.frameworks.tests.net.R;
50 import com.android.internal.util.HexDump;
51 import java.io.File;
52 import java.io.FileDescriptor;
53 import java.io.FileOutputStream;
54 import java.io.IOException;
55 import java.io.InputStream;
56 import java.io.OutputStream;
57 import java.net.InetAddress;
58 import java.nio.ByteBuffer;
59 import java.util.List;
60 import java.util.Random;
61 import libcore.io.IoUtils;
62 import libcore.io.Streams;
63 import org.junit.Before;
64 import org.junit.Test;
65 import org.junit.runner.RunWith;
66 import org.mockito.ArgumentCaptor;
67 import org.mockito.Mock;
68 import org.mockito.MockitoAnnotations;
69 
70 /**
71  * Tests for APF program generator and interpreter.
72  *
73  * Build, install and run with:
74  *  runtest frameworks-net -c android.net.apf.ApfTest
75  */
76 @RunWith(AndroidJUnit4.class)
77 @SmallTest
78 public class ApfTest {
79     private static final int TIMEOUT_MS = 500;
80     private final static int MIN_APF_VERSION = 2;
81 
82     @Mock IpConnectivityLog mLog;
83     @Mock Context mContext;
84 
85     @Before
setUp()86     public void setUp() throws Exception {
87         MockitoAnnotations.initMocks(this);
88         // Load up native shared library containing APF interpreter exposed via JNI.
89         System.loadLibrary("frameworksnettestsjni");
90     }
91 
92     // Expected return codes from APF interpreter.
93     private final static int PASS = 1;
94     private final static int DROP = 0;
95     // Interpreter will just accept packets without link layer headers, so pad fake packet to at
96     // least the minimum packet size.
97     private final static int MIN_PKT_SIZE = 15;
98 
99     private static final ApfCapabilities MOCK_APF_CAPABILITIES =
100       new ApfCapabilities(2, 1700, ARPHRD_ETHER);
101 
102     private final static boolean DROP_MULTICAST = true;
103     private final static boolean ALLOW_MULTICAST = false;
104 
105     private final static boolean DROP_802_3_FRAMES = true;
106     private final static boolean ALLOW_802_3_FRAMES = false;
107 
getDefaultConfig()108     private static ApfConfiguration getDefaultConfig() {
109         ApfFilter.ApfConfiguration config = new ApfConfiguration();
110         config.apfCapabilities = MOCK_APF_CAPABILITIES;
111         config.multicastFilter = ALLOW_MULTICAST;
112         config.ieee802_3Filter = ALLOW_802_3_FRAMES;
113         config.ethTypeBlackList = new int[0];
114         return config;
115     }
116 
label(int code)117     private static String label(int code) {
118         switch (code) {
119             case PASS: return "PASS";
120             case DROP: return "DROP";
121             default:   return "UNKNOWN";
122         }
123     }
124 
assertReturnCodesEqual(int expected, int got)125     private static void assertReturnCodesEqual(int expected, int got) {
126         assertEquals(label(expected), label(got));
127     }
128 
assertVerdict(int expected, byte[] program, byte[] packet, int filterAge)129     private void assertVerdict(int expected, byte[] program, byte[] packet, int filterAge) {
130         assertReturnCodesEqual(expected, apfSimulate(program, packet, null, filterAge));
131     }
132 
assertVerdict(int expected, byte[] program, byte[] packet)133     private void assertVerdict(int expected, byte[] program, byte[] packet) {
134         assertReturnCodesEqual(expected, apfSimulate(program, packet, null, 0));
135     }
136 
assertPass(byte[] program, byte[] packet, int filterAge)137     private void assertPass(byte[] program, byte[] packet, int filterAge) {
138         assertVerdict(PASS, program, packet, filterAge);
139     }
140 
assertPass(byte[] program, byte[] packet)141     private void assertPass(byte[] program, byte[] packet) {
142         assertVerdict(PASS, program, packet);
143     }
144 
assertDrop(byte[] program, byte[] packet, int filterAge)145     private void assertDrop(byte[] program, byte[] packet, int filterAge) {
146         assertVerdict(DROP, program, packet, filterAge);
147     }
148 
assertDrop(byte[] program, byte[] packet)149     private void assertDrop(byte[] program, byte[] packet) {
150         assertVerdict(DROP, program, packet);
151     }
152 
assertProgramEquals(byte[] expected, byte[] program)153     private void assertProgramEquals(byte[] expected, byte[] program) throws AssertionError {
154         // assertArrayEquals() would only print one byte, making debugging difficult.
155         if (!java.util.Arrays.equals(expected, program)) {
156             throw new AssertionError(
157                     "\nexpected: " + HexDump.toHexString(expected) +
158                     "\nactual:   " + HexDump.toHexString(program));
159         }
160     }
161 
assertDataMemoryContents( int expected, byte[] program, byte[] packet, byte[] data, byte[] expected_data)162     private void assertDataMemoryContents(
163             int expected, byte[] program, byte[] packet, byte[] data, byte[] expected_data)
164             throws IllegalInstructionException, Exception {
165         assertReturnCodesEqual(expected, apfSimulate(program, packet, data, 0 /* filterAge */));
166 
167         // assertArrayEquals() would only print one byte, making debugging difficult.
168         if (!java.util.Arrays.equals(expected_data, data)) {
169             throw new Exception(
170                     "\nprogram:     " + HexDump.toHexString(program) +
171                     "\ndata memory: " + HexDump.toHexString(data) +
172                     "\nexpected:    " + HexDump.toHexString(expected_data));
173         }
174     }
175 
assertVerdict(int expected, ApfGenerator gen, byte[] packet, int filterAge)176     private void assertVerdict(int expected, ApfGenerator gen, byte[] packet, int filterAge)
177             throws IllegalInstructionException {
178         assertReturnCodesEqual(expected, apfSimulate(gen.generate(), packet, null,
179               filterAge));
180     }
181 
assertPass(ApfGenerator gen, byte[] packet, int filterAge)182     private void assertPass(ApfGenerator gen, byte[] packet, int filterAge)
183             throws IllegalInstructionException {
184         assertVerdict(PASS, gen, packet, filterAge);
185     }
186 
assertDrop(ApfGenerator gen, byte[] packet, int filterAge)187     private void assertDrop(ApfGenerator gen, byte[] packet, int filterAge)
188             throws IllegalInstructionException {
189         assertVerdict(DROP, gen, packet, filterAge);
190     }
191 
assertPass(ApfGenerator gen)192     private void assertPass(ApfGenerator gen)
193             throws IllegalInstructionException {
194         assertVerdict(PASS, gen, new byte[MIN_PKT_SIZE], 0);
195     }
196 
assertDrop(ApfGenerator gen)197     private void assertDrop(ApfGenerator gen)
198             throws IllegalInstructionException {
199         assertVerdict(DROP, gen, new byte[MIN_PKT_SIZE], 0);
200     }
201 
202     /**
203      * Test each instruction by generating a program containing the instruction,
204      * generating bytecode for that program and running it through the
205      * interpreter to verify it functions correctly.
206      */
207     @Test
testApfInstructions()208     public void testApfInstructions() throws IllegalInstructionException {
209         // Empty program should pass because having the program counter reach the
210         // location immediately after the program indicates the packet should be
211         // passed to the AP.
212         ApfGenerator gen = new ApfGenerator(MIN_APF_VERSION);
213         assertPass(gen);
214 
215         // Test jumping to pass label.
216         gen = new ApfGenerator(MIN_APF_VERSION);
217         gen.addJump(gen.PASS_LABEL);
218         byte[] program = gen.generate();
219         assertEquals(1, program.length);
220         assertEquals((14 << 3) | (0 << 1) | 0, program[0]);
221         assertPass(program, new byte[MIN_PKT_SIZE], 0);
222 
223         // Test jumping to drop label.
224         gen = new ApfGenerator(MIN_APF_VERSION);
225         gen.addJump(gen.DROP_LABEL);
226         program = gen.generate();
227         assertEquals(2, program.length);
228         assertEquals((14 << 3) | (1 << 1) | 0, program[0]);
229         assertEquals(1, program[1]);
230         assertDrop(program, new byte[15], 15);
231 
232         // Test jumping if equal to 0.
233         gen = new ApfGenerator(MIN_APF_VERSION);
234         gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
235         assertDrop(gen);
236 
237         // Test jumping if not equal to 0.
238         gen = new ApfGenerator(MIN_APF_VERSION);
239         gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL);
240         assertPass(gen);
241         gen = new ApfGenerator(MIN_APF_VERSION);
242         gen.addLoadImmediate(Register.R0, 1);
243         gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL);
244         assertDrop(gen);
245 
246         // Test jumping if registers equal.
247         gen = new ApfGenerator(MIN_APF_VERSION);
248         gen.addJumpIfR0EqualsR1(gen.DROP_LABEL);
249         assertDrop(gen);
250 
251         // Test jumping if registers not equal.
252         gen = new ApfGenerator(MIN_APF_VERSION);
253         gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL);
254         assertPass(gen);
255         gen = new ApfGenerator(MIN_APF_VERSION);
256         gen.addLoadImmediate(Register.R0, 1);
257         gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL);
258         assertDrop(gen);
259 
260         // Test load immediate.
261         gen = new ApfGenerator(MIN_APF_VERSION);
262         gen.addLoadImmediate(Register.R0, 1234567890);
263         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
264         assertDrop(gen);
265 
266         // Test add.
267         gen = new ApfGenerator(MIN_APF_VERSION);
268         gen.addAdd(1234567890);
269         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
270         assertDrop(gen);
271 
272         // Test subtract.
273         gen = new ApfGenerator(MIN_APF_VERSION);
274         gen.addAdd(-1234567890);
275         gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
276         assertDrop(gen);
277 
278         // Test or.
279         gen = new ApfGenerator(MIN_APF_VERSION);
280         gen.addOr(1234567890);
281         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
282         assertDrop(gen);
283 
284         // Test and.
285         gen = new ApfGenerator(MIN_APF_VERSION);
286         gen.addLoadImmediate(Register.R0, 1234567890);
287         gen.addAnd(123456789);
288         gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL);
289         assertDrop(gen);
290 
291         // Test left shift.
292         gen = new ApfGenerator(MIN_APF_VERSION);
293         gen.addLoadImmediate(Register.R0, 1234567890);
294         gen.addLeftShift(1);
295         gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL);
296         assertDrop(gen);
297 
298         // Test right shift.
299         gen = new ApfGenerator(MIN_APF_VERSION);
300         gen.addLoadImmediate(Register.R0, 1234567890);
301         gen.addRightShift(1);
302         gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL);
303         assertDrop(gen);
304 
305         // Test multiply.
306         gen = new ApfGenerator(MIN_APF_VERSION);
307         gen.addLoadImmediate(Register.R0, 1234567890);
308         gen.addMul(2);
309         gen.addJumpIfR0Equals(1234567890 * 2, gen.DROP_LABEL);
310         assertDrop(gen);
311 
312         // Test divide.
313         gen = new ApfGenerator(MIN_APF_VERSION);
314         gen.addLoadImmediate(Register.R0, 1234567890);
315         gen.addDiv(2);
316         gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL);
317         assertDrop(gen);
318 
319         // Test divide by zero.
320         gen = new ApfGenerator(MIN_APF_VERSION);
321         gen.addDiv(0);
322         gen.addJump(gen.DROP_LABEL);
323         assertPass(gen);
324 
325         // Test add.
326         gen = new ApfGenerator(MIN_APF_VERSION);
327         gen.addLoadImmediate(Register.R1, 1234567890);
328         gen.addAddR1();
329         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
330         assertDrop(gen);
331 
332         // Test subtract.
333         gen = new ApfGenerator(MIN_APF_VERSION);
334         gen.addLoadImmediate(Register.R1, -1234567890);
335         gen.addAddR1();
336         gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
337         assertDrop(gen);
338 
339         // Test or.
340         gen = new ApfGenerator(MIN_APF_VERSION);
341         gen.addLoadImmediate(Register.R1, 1234567890);
342         gen.addOrR1();
343         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
344         assertDrop(gen);
345 
346         // Test and.
347         gen = new ApfGenerator(MIN_APF_VERSION);
348         gen.addLoadImmediate(Register.R0, 1234567890);
349         gen.addLoadImmediate(Register.R1, 123456789);
350         gen.addAndR1();
351         gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL);
352         assertDrop(gen);
353 
354         // Test left shift.
355         gen = new ApfGenerator(MIN_APF_VERSION);
356         gen.addLoadImmediate(Register.R0, 1234567890);
357         gen.addLoadImmediate(Register.R1, 1);
358         gen.addLeftShiftR1();
359         gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL);
360         assertDrop(gen);
361 
362         // Test right shift.
363         gen = new ApfGenerator(MIN_APF_VERSION);
364         gen.addLoadImmediate(Register.R0, 1234567890);
365         gen.addLoadImmediate(Register.R1, -1);
366         gen.addLeftShiftR1();
367         gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL);
368         assertDrop(gen);
369 
370         // Test multiply.
371         gen = new ApfGenerator(MIN_APF_VERSION);
372         gen.addLoadImmediate(Register.R0, 1234567890);
373         gen.addLoadImmediate(Register.R1, 2);
374         gen.addMulR1();
375         gen.addJumpIfR0Equals(1234567890 * 2, gen.DROP_LABEL);
376         assertDrop(gen);
377 
378         // Test divide.
379         gen = new ApfGenerator(MIN_APF_VERSION);
380         gen.addLoadImmediate(Register.R0, 1234567890);
381         gen.addLoadImmediate(Register.R1, 2);
382         gen.addDivR1();
383         gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL);
384         assertDrop(gen);
385 
386         // Test divide by zero.
387         gen = new ApfGenerator(MIN_APF_VERSION);
388         gen.addDivR1();
389         gen.addJump(gen.DROP_LABEL);
390         assertPass(gen);
391 
392         // Test byte load.
393         gen = new ApfGenerator(MIN_APF_VERSION);
394         gen.addLoad8(Register.R0, 1);
395         gen.addJumpIfR0Equals(45, gen.DROP_LABEL);
396         assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
397 
398         // Test out of bounds load.
399         gen = new ApfGenerator(MIN_APF_VERSION);
400         gen.addLoad8(Register.R0, 16);
401         gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
402         assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
403 
404         // Test half-word load.
405         gen = new ApfGenerator(MIN_APF_VERSION);
406         gen.addLoad16(Register.R0, 1);
407         gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL);
408         assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
409 
410         // Test word load.
411         gen = new ApfGenerator(MIN_APF_VERSION);
412         gen.addLoad32(Register.R0, 1);
413         gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL);
414         assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0);
415 
416         // Test byte indexed load.
417         gen = new ApfGenerator(MIN_APF_VERSION);
418         gen.addLoadImmediate(Register.R1, 1);
419         gen.addLoad8Indexed(Register.R0, 0);
420         gen.addJumpIfR0Equals(45, gen.DROP_LABEL);
421         assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
422 
423         // Test out of bounds indexed load.
424         gen = new ApfGenerator(MIN_APF_VERSION);
425         gen.addLoadImmediate(Register.R1, 8);
426         gen.addLoad8Indexed(Register.R0, 8);
427         gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
428         assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
429 
430         // Test half-word indexed load.
431         gen = new ApfGenerator(MIN_APF_VERSION);
432         gen.addLoadImmediate(Register.R1, 1);
433         gen.addLoad16Indexed(Register.R0, 0);
434         gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL);
435         assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
436 
437         // Test word indexed load.
438         gen = new ApfGenerator(MIN_APF_VERSION);
439         gen.addLoadImmediate(Register.R1, 1);
440         gen.addLoad32Indexed(Register.R0, 0);
441         gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL);
442         assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0);
443 
444         // Test jumping if greater than.
445         gen = new ApfGenerator(MIN_APF_VERSION);
446         gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL);
447         assertPass(gen);
448         gen = new ApfGenerator(MIN_APF_VERSION);
449         gen.addLoadImmediate(Register.R0, 1);
450         gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL);
451         assertDrop(gen);
452 
453         // Test jumping if less than.
454         gen = new ApfGenerator(MIN_APF_VERSION);
455         gen.addJumpIfR0LessThan(0, gen.DROP_LABEL);
456         assertPass(gen);
457         gen = new ApfGenerator(MIN_APF_VERSION);
458         gen.addJumpIfR0LessThan(1, gen.DROP_LABEL);
459         assertDrop(gen);
460 
461         // Test jumping if any bits set.
462         gen = new ApfGenerator(MIN_APF_VERSION);
463         gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
464         assertPass(gen);
465         gen = new ApfGenerator(MIN_APF_VERSION);
466         gen.addLoadImmediate(Register.R0, 1);
467         gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
468         assertDrop(gen);
469         gen = new ApfGenerator(MIN_APF_VERSION);
470         gen.addLoadImmediate(Register.R0, 3);
471         gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
472         assertDrop(gen);
473 
474         // Test jumping if register greater than.
475         gen = new ApfGenerator(MIN_APF_VERSION);
476         gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL);
477         assertPass(gen);
478         gen = new ApfGenerator(MIN_APF_VERSION);
479         gen.addLoadImmediate(Register.R0, 2);
480         gen.addLoadImmediate(Register.R1, 1);
481         gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL);
482         assertDrop(gen);
483 
484         // Test jumping if register less than.
485         gen = new ApfGenerator(MIN_APF_VERSION);
486         gen.addJumpIfR0LessThanR1(gen.DROP_LABEL);
487         assertPass(gen);
488         gen = new ApfGenerator(MIN_APF_VERSION);
489         gen.addLoadImmediate(Register.R1, 1);
490         gen.addJumpIfR0LessThanR1(gen.DROP_LABEL);
491         assertDrop(gen);
492 
493         // Test jumping if any bits set in register.
494         gen = new ApfGenerator(MIN_APF_VERSION);
495         gen.addLoadImmediate(Register.R1, 3);
496         gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
497         assertPass(gen);
498         gen = new ApfGenerator(MIN_APF_VERSION);
499         gen.addLoadImmediate(Register.R1, 3);
500         gen.addLoadImmediate(Register.R0, 1);
501         gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
502         assertDrop(gen);
503         gen = new ApfGenerator(MIN_APF_VERSION);
504         gen.addLoadImmediate(Register.R1, 3);
505         gen.addLoadImmediate(Register.R0, 3);
506         gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
507         assertDrop(gen);
508 
509         // Test load from memory.
510         gen = new ApfGenerator(MIN_APF_VERSION);
511         gen.addLoadFromMemory(Register.R0, 0);
512         gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
513         assertDrop(gen);
514 
515         // Test store to memory.
516         gen = new ApfGenerator(MIN_APF_VERSION);
517         gen.addLoadImmediate(Register.R1, 1234567890);
518         gen.addStoreToMemory(Register.R1, 12);
519         gen.addLoadFromMemory(Register.R0, 12);
520         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
521         assertDrop(gen);
522 
523         // Test filter age pre-filled memory.
524         gen = new ApfGenerator(MIN_APF_VERSION);
525         gen.addLoadFromMemory(Register.R0, gen.FILTER_AGE_MEMORY_SLOT);
526         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
527         assertDrop(gen, new byte[MIN_PKT_SIZE], 1234567890);
528 
529         // Test packet size pre-filled memory.
530         gen = new ApfGenerator(MIN_APF_VERSION);
531         gen.addLoadFromMemory(Register.R0, gen.PACKET_SIZE_MEMORY_SLOT);
532         gen.addJumpIfR0Equals(MIN_PKT_SIZE, gen.DROP_LABEL);
533         assertDrop(gen);
534 
535         // Test IPv4 header size pre-filled memory.
536         gen = new ApfGenerator(MIN_APF_VERSION);
537         gen.addLoadFromMemory(Register.R0, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
538         gen.addJumpIfR0Equals(20, gen.DROP_LABEL);
539         assertDrop(gen, new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x45}, 0);
540 
541         // Test not.
542         gen = new ApfGenerator(MIN_APF_VERSION);
543         gen.addLoadImmediate(Register.R0, 1234567890);
544         gen.addNot(Register.R0);
545         gen.addJumpIfR0Equals(~1234567890, gen.DROP_LABEL);
546         assertDrop(gen);
547 
548         // Test negate.
549         gen = new ApfGenerator(MIN_APF_VERSION);
550         gen.addLoadImmediate(Register.R0, 1234567890);
551         gen.addNeg(Register.R0);
552         gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
553         assertDrop(gen);
554 
555         // Test move.
556         gen = new ApfGenerator(MIN_APF_VERSION);
557         gen.addLoadImmediate(Register.R1, 1234567890);
558         gen.addMove(Register.R0);
559         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
560         assertDrop(gen);
561         gen = new ApfGenerator(MIN_APF_VERSION);
562         gen.addLoadImmediate(Register.R0, 1234567890);
563         gen.addMove(Register.R1);
564         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
565         assertDrop(gen);
566 
567         // Test swap.
568         gen = new ApfGenerator(MIN_APF_VERSION);
569         gen.addLoadImmediate(Register.R1, 1234567890);
570         gen.addSwap();
571         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
572         assertDrop(gen);
573         gen = new ApfGenerator(MIN_APF_VERSION);
574         gen.addLoadImmediate(Register.R0, 1234567890);
575         gen.addSwap();
576         gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
577         assertDrop(gen);
578 
579         // Test jump if bytes not equal.
580         gen = new ApfGenerator(MIN_APF_VERSION);
581         gen.addLoadImmediate(Register.R0, 1);
582         gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
583         program = gen.generate();
584         assertEquals(6, program.length);
585         assertEquals((13 << 3) | (1 << 1) | 0, program[0]);
586         assertEquals(1, program[1]);
587         assertEquals(((20 << 3) | (1 << 1) | 0) - 256, program[2]);
588         assertEquals(1, program[3]);
589         assertEquals(1, program[4]);
590         assertEquals(123, program[5]);
591         assertDrop(program, new byte[MIN_PKT_SIZE], 0);
592         gen = new ApfGenerator(MIN_APF_VERSION);
593         gen.addLoadImmediate(Register.R0, 1);
594         gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
595         byte[] packet123 = {0,123,0,0,0,0,0,0,0,0,0,0,0,0,0};
596         assertPass(gen, packet123, 0);
597         gen = new ApfGenerator(MIN_APF_VERSION);
598         gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
599         assertDrop(gen, packet123, 0);
600         gen = new ApfGenerator(MIN_APF_VERSION);
601         gen.addLoadImmediate(Register.R0, 1);
602         gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,30,4,5}, gen.DROP_LABEL);
603         byte[] packet12345 = {0,1,2,3,4,5,0,0,0,0,0,0,0,0,0};
604         assertDrop(gen, packet12345, 0);
605         gen = new ApfGenerator(MIN_APF_VERSION);
606         gen.addLoadImmediate(Register.R0, 1);
607         gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,3,4,5}, gen.DROP_LABEL);
608         assertPass(gen, packet12345, 0);
609     }
610 
611     @Test(expected = ApfGenerator.IllegalInstructionException.class)
testApfGeneratorWantsV2OrGreater()612     public void testApfGeneratorWantsV2OrGreater() throws Exception {
613         // The minimum supported APF version is 2.
614         new ApfGenerator(1);
615     }
616 
617     @Test
testApfDataOpcodesWantApfV3()618     public void testApfDataOpcodesWantApfV3() throws IllegalInstructionException, Exception {
619         ApfGenerator gen = new ApfGenerator(MIN_APF_VERSION);
620         try {
621             gen.addStoreData(Register.R0, 0);
622             fail();
623         } catch (IllegalInstructionException expected) {
624             /* pass */
625         }
626         try {
627             gen.addLoadData(Register.R0, 0);
628             fail();
629         } catch (IllegalInstructionException expected) {
630             /* pass */
631         }
632     }
633 
634     /**
635      * Test that the generator emits immediates using the shortest possible encoding.
636      */
637     @Test
testImmediateEncoding()638     public void testImmediateEncoding() throws IllegalInstructionException {
639         final int LI_OPCODE = 13 << 3;
640         ApfGenerator gen;
641 
642         // 0-byte immediate: li R0, 0
643         gen = new ApfGenerator(3);
644         gen.addLoadImmediate(Register.R0, 0);
645         assertProgramEquals(new byte[]{LI_OPCODE | (0 << 1)}, gen.generate());
646 
647         // 1-byte immediate: li R0, 42
648         gen = new ApfGenerator(3);
649         gen.addLoadImmediate(Register.R0, 42);
650         assertProgramEquals(new byte[]{LI_OPCODE | (1 << 1), 42}, gen.generate());
651 
652         // 2-byte immediate: li R1, 0x1234
653         gen = new ApfGenerator(3);
654         gen.addLoadImmediate(Register.R1, 0x1234);
655         assertProgramEquals(new byte[]{LI_OPCODE | (2 << 1) | 1 , 0x12, 0x34}, gen.generate());
656 
657         // 4-byte immediate: li R0, 0x12345678
658         gen = new ApfGenerator(3);
659         gen.addLoadImmediate(Register.R0, 0x12345678);
660         assertProgramEquals(
661                 new byte[]{LI_OPCODE | (3 << 1), 0x12, 0x34, 0x56, 0x78},
662                 gen.generate());
663     }
664 
665     /**
666      * Test that the generator emits negative immediates using the shortest possible encoding.
667      */
668     @Test
testNegativeImmediateEncoding()669     public void testNegativeImmediateEncoding() throws IllegalInstructionException {
670         final int LI_OPCODE = 13 << 3;
671         ApfGenerator gen;
672 
673         // 1-byte negative immediate: li R0, -42
674         gen = new ApfGenerator(3);
675         gen.addLoadImmediate(Register.R0, -42);
676         assertProgramEquals(new byte[]{LI_OPCODE | (1 << 1), -42}, gen.generate());
677 
678         // 2-byte negative immediate: li R1, -0x1234
679         gen = new ApfGenerator(3);
680         gen.addLoadImmediate(Register.R1, -0x1122);
681         assertProgramEquals(new byte[]{LI_OPCODE | (2 << 1) | 1, (byte)0xEE, (byte)0xDE},
682                 gen.generate());
683 
684         // 4-byte negative immediate: li R0, -0x11223344
685         gen = new ApfGenerator(3);
686         gen.addLoadImmediate(Register.R0, -0x11223344);
687         assertProgramEquals(
688                 new byte[]{LI_OPCODE | (3 << 1), (byte)0xEE, (byte)0xDD, (byte)0xCC, (byte)0xBC},
689                 gen.generate());
690     }
691 
692     @Test
testApfDataWrite()693     public void testApfDataWrite() throws IllegalInstructionException, Exception {
694         byte[] packet = new byte[MIN_PKT_SIZE];
695         byte[] data = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
696         byte[] expected_data = data.clone();
697 
698         // No memory access instructions: should leave the data segment untouched.
699         ApfGenerator gen = new ApfGenerator(3);
700         assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
701 
702         // Expect value 0x87654321 to be stored starting from address -11 from the end of the
703         // data buffer, in big-endian order.
704         gen = new ApfGenerator(3);
705         gen.addLoadImmediate(Register.R0, 0x87654321);
706         gen.addLoadImmediate(Register.R1, -5);
707         gen.addStoreData(Register.R0, -6);  // -5 + -6 = -11 (offset +5 with data_len=16)
708         expected_data[5] = (byte)0x87;
709         expected_data[6] = (byte)0x65;
710         expected_data[7] = (byte)0x43;
711         expected_data[8] = (byte)0x21;
712         assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
713     }
714 
715     @Test
testApfDataRead()716     public void testApfDataRead() throws IllegalInstructionException, Exception {
717         // Program that DROPs if address 10 (-6) contains 0x87654321.
718         ApfGenerator gen = new ApfGenerator(3);
719         gen.addLoadImmediate(Register.R1, 10);
720         gen.addLoadData(Register.R0, -16);  // 10 + -16 = -6 (offset +10 with data_len=16)
721         gen.addJumpIfR0Equals(0x87654321, gen.DROP_LABEL);
722         byte[] program = gen.generate();
723         byte[] packet = new byte[MIN_PKT_SIZE];
724 
725         // Content is incorrect (last byte does not match) -> PASS
726         byte[] data = new byte[16];
727         data[10] = (byte)0x87;
728         data[11] = (byte)0x65;
729         data[12] = (byte)0x43;
730         data[13] = (byte)0x00;  // != 0x21
731         byte[] expected_data = data.clone();
732         assertDataMemoryContents(PASS, program, packet, data, expected_data);
733 
734         // Fix the last byte -> conditional jump taken -> DROP
735         data[13] = (byte)0x21;
736         expected_data = data;
737         assertDataMemoryContents(DROP, program, packet, data, expected_data);
738     }
739 
740     @Test
testApfDataReadModifyWrite()741     public void testApfDataReadModifyWrite() throws IllegalInstructionException, Exception {
742         ApfGenerator gen = new ApfGenerator(3);
743         gen.addLoadImmediate(Register.R1, -22);
744         gen.addLoadData(Register.R0, 0);  // Load from address 32 -22 + 0 = 10
745         gen.addAdd(0x78453412);  // 87654321 + 78453412 = FFAA7733
746         gen.addStoreData(Register.R0, 4);  // Write back to address 32 -22 + 4 = 14
747 
748         byte[] packet = new byte[MIN_PKT_SIZE];
749         byte[] data = new byte[32];
750         data[10] = (byte)0x87;
751         data[11] = (byte)0x65;
752         data[12] = (byte)0x43;
753         data[13] = (byte)0x21;
754         byte[] expected_data = data.clone();
755         expected_data[14] = (byte)0xFF;
756         expected_data[15] = (byte)0xAA;
757         expected_data[16] = (byte)0x77;
758         expected_data[17] = (byte)0x33;
759         assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
760     }
761 
762     @Test
testApfDataBoundChecking()763     public void testApfDataBoundChecking() throws IllegalInstructionException, Exception {
764         byte[] packet = new byte[MIN_PKT_SIZE];
765         byte[] data = new byte[32];
766         byte[] expected_data = data;
767 
768         // Program that DROPs unconditionally. This is our the baseline.
769         ApfGenerator gen = new ApfGenerator(3);
770         gen.addLoadImmediate(Register.R0, 3);
771         gen.addLoadData(Register.R1, 7);
772         gen.addJump(gen.DROP_LABEL);
773         assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data);
774 
775         // Same program as before, but this time we're trying to load past the end of the data.
776         gen = new ApfGenerator(3);
777         gen.addLoadImmediate(Register.R0, 20);
778         gen.addLoadData(Register.R1, 15);  // 20 + 15 > 32
779         gen.addJump(gen.DROP_LABEL);  // Not reached.
780         assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
781 
782         // Subtracting an immediate should work...
783         gen = new ApfGenerator(3);
784         gen.addLoadImmediate(Register.R0, 20);
785         gen.addLoadData(Register.R1, -4);
786         gen.addJump(gen.DROP_LABEL);
787         assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data);
788 
789         // ...and underflowing simply wraps around to the end of the buffer...
790         gen = new ApfGenerator(3);
791         gen.addLoadImmediate(Register.R0, 20);
792         gen.addLoadData(Register.R1, -30);
793         gen.addJump(gen.DROP_LABEL);
794         assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data);
795 
796         // ...but doesn't allow accesses before the start of the buffer
797         gen = new ApfGenerator(3);
798         gen.addLoadImmediate(Register.R0, 20);
799         gen.addLoadData(Register.R1, -1000);
800         gen.addJump(gen.DROP_LABEL);  // Not reached.
801         assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
802     }
803 
804     /**
805      * Generate some BPF programs, translate them to APF, then run APF and BPF programs
806      * over packet traces and verify both programs filter out the same packets.
807      */
808     @Test
testApfAgainstBpf()809     public void testApfAgainstBpf() throws Exception {
810         String[] tcpdump_filters = new String[]{ "udp", "tcp", "icmp", "icmp6", "udp port 53",
811                 "arp", "dst 239.255.255.250", "arp or tcp or udp port 53", "net 192.168.1.0/24",
812                 "arp or icmp6 or portrange 53-54", "portrange 53-54 or portrange 100-50000",
813                 "tcp[tcpflags] & (tcp-ack|tcp-fin) != 0 and (ip[2:2] > 57 or icmp)" };
814         String pcap_filename = stageFile(R.raw.apf);
815         for (String tcpdump_filter : tcpdump_filters) {
816             byte[] apf_program = Bpf2Apf.convert(compileToBpf(tcpdump_filter));
817             assertTrue("Failed to match for filter: " + tcpdump_filter,
818                     compareBpfApf(tcpdump_filter, pcap_filename, apf_program));
819         }
820     }
821 
822     private class MockIpClientCallback extends IpClient.Callback {
823         private final ConditionVariable mGotApfProgram = new ConditionVariable();
824         private byte[] mLastApfProgram;
825 
826         @Override
installPacketFilter(byte[] filter)827         public void installPacketFilter(byte[] filter) {
828             mLastApfProgram = filter;
829             mGotApfProgram.open();
830         }
831 
resetApfProgramWait()832         public void resetApfProgramWait() {
833             mGotApfProgram.close();
834         }
835 
getApfProgram()836         public byte[] getApfProgram() {
837             assertTrue(mGotApfProgram.block(TIMEOUT_MS));
838             return mLastApfProgram;
839         }
840 
assertNoProgramUpdate()841         public void assertNoProgramUpdate() {
842             assertFalse(mGotApfProgram.block(TIMEOUT_MS));
843         }
844     }
845 
846     private static class TestApfFilter extends ApfFilter {
847         public final static byte[] MOCK_MAC_ADDR = {1,2,3,4,5,6};
848 
849         private FileDescriptor mWriteSocket;
850         private final long mFixedTimeMs = SystemClock.elapsedRealtime();
851 
TestApfFilter(Context context, ApfConfiguration config, IpClient.Callback ipClientCallback, IpConnectivityLog log)852         public TestApfFilter(Context context, ApfConfiguration config,
853                 IpClient.Callback ipClientCallback, IpConnectivityLog log) throws Exception {
854             super(context, config, InterfaceParams.getByName("lo"), ipClientCallback, log);
855         }
856 
857         // Pretend an RA packet has been received and show it to ApfFilter.
pretendPacketReceived(byte[] packet)858         public void pretendPacketReceived(byte[] packet) throws IOException, ErrnoException {
859             // ApfFilter's ReceiveThread will be waiting to read this.
860             Os.write(mWriteSocket, packet, 0, packet.length);
861         }
862 
863         @Override
currentTimeSeconds()864         protected long currentTimeSeconds() {
865             return mFixedTimeMs / DateUtils.SECOND_IN_MILLIS;
866         }
867 
868         @Override
maybeStartFilter()869         void maybeStartFilter() {
870             mHardwareAddress = MOCK_MAC_ADDR;
871             installNewProgramLocked();
872 
873             // Create two sockets, "readSocket" and "mWriteSocket" and connect them together.
874             FileDescriptor readSocket = new FileDescriptor();
875             mWriteSocket = new FileDescriptor();
876             try {
877                 Os.socketpair(AF_UNIX, SOCK_STREAM, 0, mWriteSocket, readSocket);
878             } catch (ErrnoException e) {
879                 fail();
880                 return;
881             }
882             // Now pass readSocket to ReceiveThread as if it was setup to read raw RAs.
883             // This allows us to pretend RA packets have been recieved via pretendPacketReceived().
884             mReceiveThread = new ReceiveThread(readSocket);
885             mReceiveThread.start();
886         }
887 
888         @Override
shutdown()889         public void shutdown() {
890             super.shutdown();
891             IoUtils.closeQuietly(mWriteSocket);
892         }
893     }
894 
895     private static final int ETH_HEADER_LEN = 14;
896     private static final int ETH_DEST_ADDR_OFFSET = 0;
897     private static final int ETH_ETHERTYPE_OFFSET = 12;
898     private static final byte[] ETH_BROADCAST_MAC_ADDRESS =
899             {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
900 
901     private static final int IPV4_VERSION_IHL_OFFSET = ETH_HEADER_LEN + 0;
902     private static final int IPV4_PROTOCOL_OFFSET = ETH_HEADER_LEN + 9;
903     private static final int IPV4_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 16;
904     private static final byte[] IPV4_BROADCAST_ADDRESS =
905             {(byte) 255, (byte) 255, (byte) 255, (byte) 255};
906 
907     private static final int IPV6_NEXT_HEADER_OFFSET = ETH_HEADER_LEN + 6;
908     private static final int IPV6_HEADER_LEN = 40;
909     private static final int IPV6_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 24;
910     // The IPv6 all nodes address ff02::1
911     private static final byte[] IPV6_ALL_NODES_ADDRESS =
912             { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
913     private static final byte[] IPV6_ALL_ROUTERS_ADDRESS =
914             { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 };
915 
916     private static final int ICMP6_TYPE_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN;
917     private static final int ICMP6_ROUTER_SOLICITATION = 133;
918     private static final int ICMP6_ROUTER_ADVERTISEMENT = 134;
919     private static final int ICMP6_NEIGHBOR_SOLICITATION = 135;
920     private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136;
921 
922     private static final int ICMP6_RA_HEADER_LEN = 16;
923     private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET =
924             ETH_HEADER_LEN + IPV6_HEADER_LEN + 6;
925     private static final int ICMP6_RA_CHECKSUM_OFFSET =
926             ETH_HEADER_LEN + IPV6_HEADER_LEN + 2;
927     private static final int ICMP6_RA_OPTION_OFFSET =
928             ETH_HEADER_LEN + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN;
929 
930     private static final int ICMP6_PREFIX_OPTION_TYPE = 3;
931     private static final int ICMP6_PREFIX_OPTION_LEN = 32;
932     private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET = 4;
933     private static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET = 8;
934 
935     // From RFC6106: Recursive DNS Server option
936     private static final int ICMP6_RDNSS_OPTION_TYPE = 25;
937     // From RFC6106: DNS Search List option
938     private static final int ICMP6_DNSSL_OPTION_TYPE = 31;
939 
940     // From RFC4191: Route Information option
941     private static final int ICMP6_ROUTE_INFO_OPTION_TYPE = 24;
942     // Above three options all have the same format:
943     private static final int ICMP6_4_BYTE_OPTION_LEN = 8;
944     private static final int ICMP6_4_BYTE_LIFETIME_OFFSET = 4;
945     private static final int ICMP6_4_BYTE_LIFETIME_LEN = 4;
946 
947     private static final int UDP_HEADER_LEN = 8;
948     private static final int UDP_DESTINATION_PORT_OFFSET = ETH_HEADER_LEN + 22;
949 
950     private static final int DHCP_CLIENT_PORT = 68;
951     private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 48;
952 
953     private static final int ARP_HEADER_OFFSET = ETH_HEADER_LEN;
954     private static final byte[] ARP_IPV4_REQUEST_HEADER = {
955             0, 1, // Hardware type: Ethernet (1)
956             8, 0, // Protocol type: IP (0x0800)
957             6,    // Hardware size: 6
958             4,    // Protocol size: 4
959             0, 1  // Opcode: request (1)
960     };
961     private static final byte[] ARP_IPV4_REPLY_HEADER = {
962             0, 1, // Hardware type: Ethernet (1)
963             8, 0, // Protocol type: IP (0x0800)
964             6,    // Hardware size: 6
965             4,    // Protocol size: 4
966             0, 2  // Opcode: reply (2)
967     };
968     private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ETH_HEADER_LEN + 24;
969 
970     private static final byte[] MOCK_IPV4_ADDR           = {10, 0, 0, 1};
971     private static final byte[] MOCK_BROADCAST_IPV4_ADDR = {10, 0, 31, (byte) 255}; // prefix = 19
972     private static final byte[] MOCK_MULTICAST_IPV4_ADDR = {(byte) 224, 0, 0, 1};
973     private static final byte[] ANOTHER_IPV4_ADDR        = {10, 0, 0, 2};
974     private static final byte[] IPV4_ANY_HOST_ADDR       = {0, 0, 0, 0};
975 
976     // Helper to initialize a default apfFilter.
setupApfFilter(IpClient.Callback ipClientCallback, ApfConfiguration config)977     private ApfFilter setupApfFilter(IpClient.Callback ipClientCallback, ApfConfiguration config)
978             throws Exception {
979         LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
980         LinkProperties lp = new LinkProperties();
981         lp.addLinkAddress(link);
982         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
983         apfFilter.setLinkProperties(lp);
984         return apfFilter;
985     }
986 
987     @Test
testApfFilterIPv4()988     public void testApfFilterIPv4() throws Exception {
989         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
990         LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
991         LinkProperties lp = new LinkProperties();
992         lp.addLinkAddress(link);
993 
994         ApfConfiguration config = getDefaultConfig();
995         config.multicastFilter = DROP_MULTICAST;
996         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
997         apfFilter.setLinkProperties(lp);
998 
999         byte[] program = ipClientCallback.getApfProgram();
1000 
1001         // Verify empty packet of 100 zero bytes is passed
1002         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1003         assertPass(program, packet.array());
1004 
1005         // Verify unicast IPv4 packet is passed
1006         put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
1007         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1008         put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_IPV4_ADDR);
1009         assertPass(program, packet.array());
1010 
1011         // Verify L2 unicast to IPv4 broadcast addresses is dropped (b/30231088)
1012         put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
1013         assertDrop(program, packet.array());
1014         put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR);
1015         assertDrop(program, packet.array());
1016 
1017         // Verify multicast/broadcast IPv4, not DHCP to us, is dropped
1018         put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
1019         assertDrop(program, packet.array());
1020         packet.put(IPV4_VERSION_IHL_OFFSET, (byte)0x45);
1021         assertDrop(program, packet.array());
1022         packet.put(IPV4_PROTOCOL_OFFSET, (byte)IPPROTO_UDP);
1023         assertDrop(program, packet.array());
1024         packet.putShort(UDP_DESTINATION_PORT_OFFSET, (short)DHCP_CLIENT_PORT);
1025         assertDrop(program, packet.array());
1026         put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_MULTICAST_IPV4_ADDR);
1027         assertDrop(program, packet.array());
1028         put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR);
1029         assertDrop(program, packet.array());
1030         put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
1031         assertDrop(program, packet.array());
1032 
1033         // Verify broadcast IPv4 DHCP to us is passed
1034         put(packet, DHCP_CLIENT_MAC_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
1035         assertPass(program, packet.array());
1036 
1037         // Verify unicast IPv4 DHCP to us is passed
1038         put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
1039         assertPass(program, packet.array());
1040 
1041         apfFilter.shutdown();
1042     }
1043 
1044     @Test
testApfFilterIPv6()1045     public void testApfFilterIPv6() throws Exception {
1046         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
1047         ApfConfiguration config = getDefaultConfig();
1048         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
1049         byte[] program = ipClientCallback.getApfProgram();
1050 
1051         // Verify empty IPv6 packet is passed
1052         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1053         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
1054         assertPass(program, packet.array());
1055 
1056         // Verify empty ICMPv6 packet is passed
1057         packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
1058         assertPass(program, packet.array());
1059 
1060         // Verify empty ICMPv6 NA packet is passed
1061         packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_NEIGHBOR_ANNOUNCEMENT);
1062         assertPass(program, packet.array());
1063 
1064         // Verify ICMPv6 NA to ff02::1 is dropped
1065         put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_NODES_ADDRESS);
1066         assertDrop(program, packet.array());
1067 
1068         // Verify ICMPv6 RS to any is dropped
1069         packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_SOLICITATION);
1070         assertDrop(program, packet.array());
1071         put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_ROUTERS_ADDRESS);
1072         assertDrop(program, packet.array());
1073 
1074         apfFilter.shutdown();
1075     }
1076 
1077     @Test
testApfFilterMulticast()1078     public void testApfFilterMulticast() throws Exception {
1079         final byte[] unicastIpv4Addr   = {(byte)192,0,2,63};
1080         final byte[] broadcastIpv4Addr = {(byte)192,0,2,(byte)255};
1081         final byte[] multicastIpv4Addr = {(byte)224,0,0,1};
1082         final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb};
1083 
1084         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
1085         LinkAddress link = new LinkAddress(InetAddress.getByAddress(unicastIpv4Addr), 24);
1086         LinkProperties lp = new LinkProperties();
1087         lp.addLinkAddress(link);
1088 
1089         ApfConfiguration config = getDefaultConfig();
1090         config.ieee802_3Filter = DROP_802_3_FRAMES;
1091         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
1092         apfFilter.setLinkProperties(lp);
1093 
1094         byte[] program = ipClientCallback.getApfProgram();
1095 
1096         // Construct IPv4 and IPv6 multicast packets.
1097         ByteBuffer mcastv4packet = ByteBuffer.wrap(new byte[100]);
1098         mcastv4packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1099         put(mcastv4packet, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr);
1100 
1101         ByteBuffer mcastv6packet = ByteBuffer.wrap(new byte[100]);
1102         mcastv6packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
1103         mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_UDP);
1104         put(mcastv6packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr);
1105 
1106         // Construct IPv4 broadcast packet.
1107         ByteBuffer bcastv4packet1 = ByteBuffer.wrap(new byte[100]);
1108         bcastv4packet1.put(ETH_BROADCAST_MAC_ADDRESS);
1109         bcastv4packet1.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1110         put(bcastv4packet1, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr);
1111 
1112         ByteBuffer bcastv4packet2 = ByteBuffer.wrap(new byte[100]);
1113         bcastv4packet2.put(ETH_BROADCAST_MAC_ADDRESS);
1114         bcastv4packet2.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1115         put(bcastv4packet2, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
1116 
1117         // Construct IPv4 broadcast with L2 unicast address packet (b/30231088).
1118         ByteBuffer bcastv4unicastl2packet = ByteBuffer.wrap(new byte[100]);
1119         bcastv4unicastl2packet.put(TestApfFilter.MOCK_MAC_ADDR);
1120         bcastv4unicastl2packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1121         put(bcastv4unicastl2packet, IPV4_DEST_ADDR_OFFSET, broadcastIpv4Addr);
1122 
1123         // Verify initially disabled multicast filter is off
1124         assertPass(program, mcastv4packet.array());
1125         assertPass(program, mcastv6packet.array());
1126         assertPass(program, bcastv4packet1.array());
1127         assertPass(program, bcastv4packet2.array());
1128         assertPass(program, bcastv4unicastl2packet.array());
1129 
1130         // Turn on multicast filter and verify it works
1131         ipClientCallback.resetApfProgramWait();
1132         apfFilter.setMulticastFilter(true);
1133         program = ipClientCallback.getApfProgram();
1134         assertDrop(program, mcastv4packet.array());
1135         assertDrop(program, mcastv6packet.array());
1136         assertDrop(program, bcastv4packet1.array());
1137         assertDrop(program, bcastv4packet2.array());
1138         assertDrop(program, bcastv4unicastl2packet.array());
1139 
1140         // Turn off multicast filter and verify it's off
1141         ipClientCallback.resetApfProgramWait();
1142         apfFilter.setMulticastFilter(false);
1143         program = ipClientCallback.getApfProgram();
1144         assertPass(program, mcastv4packet.array());
1145         assertPass(program, mcastv6packet.array());
1146         assertPass(program, bcastv4packet1.array());
1147         assertPass(program, bcastv4packet2.array());
1148         assertPass(program, bcastv4unicastl2packet.array());
1149 
1150         // Verify it can be initialized to on
1151         ipClientCallback.resetApfProgramWait();
1152         apfFilter.shutdown();
1153         config.multicastFilter = DROP_MULTICAST;
1154         config.ieee802_3Filter = DROP_802_3_FRAMES;
1155         apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
1156         apfFilter.setLinkProperties(lp);
1157         program = ipClientCallback.getApfProgram();
1158         assertDrop(program, mcastv4packet.array());
1159         assertDrop(program, mcastv6packet.array());
1160         assertDrop(program, bcastv4packet1.array());
1161         assertDrop(program, bcastv4unicastl2packet.array());
1162 
1163         // Verify that ICMPv6 multicast is not dropped.
1164         mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
1165         assertPass(program, mcastv6packet.array());
1166 
1167         apfFilter.shutdown();
1168     }
1169 
1170     @Test
testApfFilterMulticastPingWhileDozing()1171     public void testApfFilterMulticastPingWhileDozing() throws Exception {
1172         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
1173         ApfFilter apfFilter = setupApfFilter(ipClientCallback, getDefaultConfig());
1174 
1175         // Construct a multicast ICMPv6 ECHO request.
1176         final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb};
1177         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1178         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
1179         packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
1180         packet.put(ICMP6_TYPE_OFFSET, (byte)ICMPV6_ECHO_REQUEST_TYPE);
1181         put(packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr);
1182 
1183         // Normally, we let multicast pings alone...
1184         assertPass(ipClientCallback.getApfProgram(), packet.array());
1185 
1186         // ...and even while dozing...
1187         apfFilter.setDozeMode(true);
1188         assertPass(ipClientCallback.getApfProgram(), packet.array());
1189 
1190         // ...but when the multicast filter is also enabled, drop the multicast pings to save power.
1191         apfFilter.setMulticastFilter(true);
1192         assertDrop(ipClientCallback.getApfProgram(), packet.array());
1193 
1194         // However, we should still let through all other ICMPv6 types.
1195         ByteBuffer raPacket = ByteBuffer.wrap(packet.array().clone());
1196         raPacket.put(ICMP6_TYPE_OFFSET, (byte)ICMPV6_ROUTER_ADVERTISEMENT);
1197         assertPass(ipClientCallback.getApfProgram(), raPacket.array());
1198 
1199         // Now wake up from doze mode to ensure that we no longer drop the packets.
1200         // (The multicast filter is still enabled at this point).
1201         apfFilter.setDozeMode(false);
1202         assertPass(ipClientCallback.getApfProgram(), packet.array());
1203 
1204         apfFilter.shutdown();
1205     }
1206 
1207     @Test
testApfFilter802_3()1208     public void testApfFilter802_3() throws Exception {
1209         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
1210         ApfConfiguration config = getDefaultConfig();
1211         ApfFilter apfFilter = setupApfFilter(ipClientCallback, config);
1212         byte[] program = ipClientCallback.getApfProgram();
1213 
1214         // Verify empty packet of 100 zero bytes is passed
1215         // Note that eth-type = 0 makes it an IEEE802.3 frame
1216         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1217         assertPass(program, packet.array());
1218 
1219         // Verify empty packet with IPv4 is passed
1220         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1221         assertPass(program, packet.array());
1222 
1223         // Verify empty IPv6 packet is passed
1224         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
1225         assertPass(program, packet.array());
1226 
1227         // Now turn on the filter
1228         ipClientCallback.resetApfProgramWait();
1229         apfFilter.shutdown();
1230         config.ieee802_3Filter = DROP_802_3_FRAMES;
1231         apfFilter = setupApfFilter(ipClientCallback, config);
1232         program = ipClientCallback.getApfProgram();
1233 
1234         // Verify that IEEE802.3 frame is dropped
1235         // In this case ethtype is used for payload length
1236         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)(100 - 14));
1237         assertDrop(program, packet.array());
1238 
1239         // Verify that IPv4 (as example of Ethernet II) frame will pass
1240         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1241         assertPass(program, packet.array());
1242 
1243         // Verify that IPv6 (as example of Ethernet II) frame will pass
1244         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
1245         assertPass(program, packet.array());
1246 
1247         apfFilter.shutdown();
1248     }
1249 
1250     @Test
testApfFilterEthTypeBL()1251     public void testApfFilterEthTypeBL() throws Exception {
1252         final int[] emptyBlackList = {};
1253         final int[] ipv4BlackList = {ETH_P_IP};
1254         final int[] ipv4Ipv6BlackList = {ETH_P_IP, ETH_P_IPV6};
1255 
1256         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
1257         ApfConfiguration config = getDefaultConfig();
1258         ApfFilter apfFilter = setupApfFilter(ipClientCallback, config);
1259         byte[] program = ipClientCallback.getApfProgram();
1260 
1261         // Verify empty packet of 100 zero bytes is passed
1262         // Note that eth-type = 0 makes it an IEEE802.3 frame
1263         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1264         assertPass(program, packet.array());
1265 
1266         // Verify empty packet with IPv4 is passed
1267         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1268         assertPass(program, packet.array());
1269 
1270         // Verify empty IPv6 packet is passed
1271         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
1272         assertPass(program, packet.array());
1273 
1274         // Now add IPv4 to the black list
1275         ipClientCallback.resetApfProgramWait();
1276         apfFilter.shutdown();
1277         config.ethTypeBlackList = ipv4BlackList;
1278         apfFilter = setupApfFilter(ipClientCallback, config);
1279         program = ipClientCallback.getApfProgram();
1280 
1281         // Verify that IPv4 frame will be dropped
1282         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1283         assertDrop(program, packet.array());
1284 
1285         // Verify that IPv6 frame will pass
1286         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
1287         assertPass(program, packet.array());
1288 
1289         // Now let us have both IPv4 and IPv6 in the black list
1290         ipClientCallback.resetApfProgramWait();
1291         apfFilter.shutdown();
1292         config.ethTypeBlackList = ipv4Ipv6BlackList;
1293         apfFilter = setupApfFilter(ipClientCallback, config);
1294         program = ipClientCallback.getApfProgram();
1295 
1296         // Verify that IPv4 frame will be dropped
1297         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1298         assertDrop(program, packet.array());
1299 
1300         // Verify that IPv6 frame will be dropped
1301         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
1302         assertDrop(program, packet.array());
1303 
1304         apfFilter.shutdown();
1305     }
1306 
getProgram(MockIpClientCallback cb, ApfFilter filter, LinkProperties lp)1307     private byte[] getProgram(MockIpClientCallback cb, ApfFilter filter, LinkProperties lp) {
1308         cb.resetApfProgramWait();
1309         filter.setLinkProperties(lp);
1310         return cb.getApfProgram();
1311     }
1312 
verifyArpFilter(byte[] program, int filterResult)1313     private void verifyArpFilter(byte[] program, int filterResult) {
1314         // Verify ARP request packet
1315         assertPass(program, arpRequestBroadcast(MOCK_IPV4_ADDR));
1316         assertVerdict(filterResult, program, arpRequestBroadcast(ANOTHER_IPV4_ADDR));
1317         assertDrop(program, arpRequestBroadcast(IPV4_ANY_HOST_ADDR));
1318 
1319         // Verify unicast ARP reply packet is always accepted.
1320         assertPass(program, arpReplyUnicast(MOCK_IPV4_ADDR));
1321         assertPass(program, arpReplyUnicast(ANOTHER_IPV4_ADDR));
1322         assertPass(program, arpReplyUnicast(IPV4_ANY_HOST_ADDR));
1323 
1324         // Verify GARP reply packets are always filtered
1325         assertDrop(program, garpReply());
1326     }
1327 
1328     @Test
testApfFilterArp()1329     public void testApfFilterArp() throws Exception {
1330         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
1331         ApfConfiguration config = getDefaultConfig();
1332         config.multicastFilter = DROP_MULTICAST;
1333         config.ieee802_3Filter = DROP_802_3_FRAMES;
1334         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
1335 
1336         // Verify initially ARP request filter is off, and GARP filter is on.
1337         verifyArpFilter(ipClientCallback.getApfProgram(), PASS);
1338 
1339         // Inform ApfFilter of our address and verify ARP filtering is on
1340         LinkAddress linkAddress = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 24);
1341         LinkProperties lp = new LinkProperties();
1342         assertTrue(lp.addLinkAddress(linkAddress));
1343         verifyArpFilter(getProgram(ipClientCallback, apfFilter, lp), DROP);
1344 
1345         // Inform ApfFilter of loss of IP and verify ARP filtering is off
1346         verifyArpFilter(getProgram(ipClientCallback, apfFilter, new LinkProperties()), PASS);
1347 
1348         apfFilter.shutdown();
1349     }
1350 
arpRequestBroadcast(byte[] tip)1351     private static byte[] arpRequestBroadcast(byte[] tip) {
1352         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1353         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
1354         put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
1355         put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
1356         put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip);
1357         return packet.array();
1358     }
1359 
arpReplyUnicast(byte[] tip)1360     private static byte[] arpReplyUnicast(byte[] tip) {
1361         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1362         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
1363         put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
1364         put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip);
1365         return packet.array();
1366     }
1367 
garpReply()1368     private static byte[] garpReply() {
1369         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1370         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
1371         put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
1372         put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
1373         put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, IPV4_ANY_HOST_ADDR);
1374         return packet.array();
1375     }
1376 
1377     // Verify that the last program pushed to the IpClient.Callback properly filters the
1378     // given packet for the given lifetime.
verifyRaLifetime(byte[] program, ByteBuffer packet, int lifetime)1379     private void verifyRaLifetime(byte[] program, ByteBuffer packet, int lifetime) {
1380         final int FRACTION_OF_LIFETIME = 6;
1381         final int ageLimit = lifetime / FRACTION_OF_LIFETIME;
1382 
1383         // Verify new program should drop RA for 1/6th its lifetime and pass afterwards.
1384         assertDrop(program, packet.array());
1385         assertDrop(program, packet.array(), ageLimit);
1386         assertPass(program, packet.array(), ageLimit + 1);
1387         assertPass(program, packet.array(), lifetime);
1388         // Verify RA checksum is ignored
1389         final short originalChecksum = packet.getShort(ICMP6_RA_CHECKSUM_OFFSET);
1390         packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)12345);
1391         assertDrop(program, packet.array());
1392         packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)-12345);
1393         assertDrop(program, packet.array());
1394         packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, originalChecksum);
1395 
1396         // Verify other changes to RA make it not match filter
1397         final byte originalFirstByte = packet.get(0);
1398         packet.put(0, (byte)-1);
1399         assertPass(program, packet.array());
1400         packet.put(0, (byte)0);
1401         assertDrop(program, packet.array());
1402         packet.put(0, originalFirstByte);
1403     }
1404 
1405     // Test that when ApfFilter is shown the given packet, it generates a program to filter it
1406     // for the given lifetime.
verifyRaLifetime(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback, ByteBuffer packet, int lifetime)1407     private void verifyRaLifetime(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback,
1408             ByteBuffer packet, int lifetime) throws IOException, ErrnoException {
1409         // Verify new program generated if ApfFilter witnesses RA
1410         ipClientCallback.resetApfProgramWait();
1411         apfFilter.pretendPacketReceived(packet.array());
1412         byte[] program = ipClientCallback.getApfProgram();
1413         verifyRaLifetime(program, packet, lifetime);
1414     }
1415 
verifyRaEvent(RaEvent expected)1416     private void verifyRaEvent(RaEvent expected) {
1417         ArgumentCaptor<Parcelable> captor = ArgumentCaptor.forClass(Parcelable.class);
1418         verify(mLog, atLeastOnce()).log(captor.capture());
1419         RaEvent got = lastRaEvent(captor.getAllValues());
1420         if (!raEventEquals(expected, got)) {
1421             assertEquals(expected, got);  // fail for printing an assertion error message.
1422         }
1423     }
1424 
lastRaEvent(List<Parcelable> events)1425     private RaEvent lastRaEvent(List<Parcelable> events) {
1426         RaEvent got = null;
1427         for (Parcelable ev : events) {
1428             if (ev instanceof RaEvent) {
1429                 got = (RaEvent) ev;
1430             }
1431         }
1432         return got;
1433     }
1434 
raEventEquals(RaEvent ev1, RaEvent ev2)1435     private boolean raEventEquals(RaEvent ev1, RaEvent ev2) {
1436         return (ev1 != null) && (ev2 != null)
1437                 && (ev1.routerLifetime == ev2.routerLifetime)
1438                 && (ev1.prefixValidLifetime == ev2.prefixValidLifetime)
1439                 && (ev1.prefixPreferredLifetime == ev2.prefixPreferredLifetime)
1440                 && (ev1.routeInfoLifetime == ev2.routeInfoLifetime)
1441                 && (ev1.rdnssLifetime == ev2.rdnssLifetime)
1442                 && (ev1.dnsslLifetime == ev2.dnsslLifetime);
1443     }
1444 
assertInvalidRa(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback, ByteBuffer packet)1445     private void assertInvalidRa(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback,
1446             ByteBuffer packet) throws IOException, ErrnoException {
1447         ipClientCallback.resetApfProgramWait();
1448         apfFilter.pretendPacketReceived(packet.array());
1449         ipClientCallback.assertNoProgramUpdate();
1450     }
1451 
1452     @Test
testApfFilterRa()1453     public void testApfFilterRa() throws Exception {
1454         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
1455         ApfConfiguration config = getDefaultConfig();
1456         config.multicastFilter = DROP_MULTICAST;
1457         config.ieee802_3Filter = DROP_802_3_FRAMES;
1458         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
1459         byte[] program = ipClientCallback.getApfProgram();
1460 
1461         final int ROUTER_LIFETIME = 1000;
1462         final int PREFIX_VALID_LIFETIME = 200;
1463         final int PREFIX_PREFERRED_LIFETIME = 100;
1464         final int RDNSS_LIFETIME  = 300;
1465         final int ROUTE_LIFETIME  = 400;
1466         // Note that lifetime of 2000 will be ignored in favor of shorter route lifetime of 1000.
1467         final int DNSSL_LIFETIME  = 2000;
1468         final int VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET = ETH_HEADER_LEN;
1469         // IPv6, traffic class = 0, flow label = 0x12345
1470         final int VERSION_TRAFFIC_CLASS_FLOW_LABEL = 0x60012345;
1471 
1472         // Verify RA is passed the first time
1473         ByteBuffer basePacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]);
1474         basePacket.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
1475         basePacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET,
1476                 VERSION_TRAFFIC_CLASS_FLOW_LABEL);
1477         basePacket.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
1478         basePacket.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_ADVERTISEMENT);
1479         basePacket.putShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET, (short)ROUTER_LIFETIME);
1480         basePacket.position(IPV6_DEST_ADDR_OFFSET);
1481         basePacket.put(IPV6_ALL_NODES_ADDRESS);
1482         assertPass(program, basePacket.array());
1483 
1484         verifyRaLifetime(apfFilter, ipClientCallback, basePacket, ROUTER_LIFETIME);
1485         verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, -1));
1486 
1487         ByteBuffer newFlowLabelPacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]);
1488         basePacket.clear();
1489         newFlowLabelPacket.put(basePacket);
1490         // Check that changes are ignored in every byte of the flow label.
1491         newFlowLabelPacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET,
1492                 VERSION_TRAFFIC_CLASS_FLOW_LABEL + 0x11111);
1493 
1494         // Ensure zero-length options cause the packet to be silently skipped.
1495         // Do this before we test other packets. http://b/29586253
1496         ByteBuffer zeroLengthOptionPacket = ByteBuffer.wrap(
1497                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
1498         basePacket.clear();
1499         zeroLengthOptionPacket.put(basePacket);
1500         zeroLengthOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE);
1501         zeroLengthOptionPacket.put((byte)0);
1502         assertInvalidRa(apfFilter, ipClientCallback, zeroLengthOptionPacket);
1503 
1504         // Generate several RAs with different options and lifetimes, and verify when
1505         // ApfFilter is shown these packets, it generates programs to filter them for the
1506         // appropriate lifetime.
1507         ByteBuffer prefixOptionPacket = ByteBuffer.wrap(
1508                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_LEN]);
1509         basePacket.clear();
1510         prefixOptionPacket.put(basePacket);
1511         prefixOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE);
1512         prefixOptionPacket.put((byte)(ICMP6_PREFIX_OPTION_LEN / 8));
1513         prefixOptionPacket.putInt(
1514                 ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET,
1515                 PREFIX_PREFERRED_LIFETIME);
1516         prefixOptionPacket.putInt(
1517                 ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET,
1518                 PREFIX_VALID_LIFETIME);
1519         verifyRaLifetime(
1520                 apfFilter, ipClientCallback, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
1521         verifyRaEvent(new RaEvent(
1522                 ROUTER_LIFETIME, PREFIX_VALID_LIFETIME, PREFIX_PREFERRED_LIFETIME, -1, -1, -1));
1523 
1524         ByteBuffer rdnssOptionPacket = ByteBuffer.wrap(
1525                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
1526         basePacket.clear();
1527         rdnssOptionPacket.put(basePacket);
1528         rdnssOptionPacket.put((byte)ICMP6_RDNSS_OPTION_TYPE);
1529         rdnssOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
1530         rdnssOptionPacket.putInt(
1531                 ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, RDNSS_LIFETIME);
1532         verifyRaLifetime(apfFilter, ipClientCallback, rdnssOptionPacket, RDNSS_LIFETIME);
1533         verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, RDNSS_LIFETIME, -1));
1534 
1535         ByteBuffer routeInfoOptionPacket = ByteBuffer.wrap(
1536                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
1537         basePacket.clear();
1538         routeInfoOptionPacket.put(basePacket);
1539         routeInfoOptionPacket.put((byte)ICMP6_ROUTE_INFO_OPTION_TYPE);
1540         routeInfoOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
1541         routeInfoOptionPacket.putInt(
1542                 ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, ROUTE_LIFETIME);
1543         verifyRaLifetime(apfFilter, ipClientCallback, routeInfoOptionPacket, ROUTE_LIFETIME);
1544         verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, ROUTE_LIFETIME, -1, -1));
1545 
1546         ByteBuffer dnsslOptionPacket = ByteBuffer.wrap(
1547                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
1548         basePacket.clear();
1549         dnsslOptionPacket.put(basePacket);
1550         dnsslOptionPacket.put((byte)ICMP6_DNSSL_OPTION_TYPE);
1551         dnsslOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
1552         dnsslOptionPacket.putInt(
1553                 ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, DNSSL_LIFETIME);
1554         verifyRaLifetime(apfFilter, ipClientCallback, dnsslOptionPacket, ROUTER_LIFETIME);
1555         verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, DNSSL_LIFETIME));
1556 
1557         // Verify that current program filters all five RAs:
1558         program = ipClientCallback.getApfProgram();
1559         verifyRaLifetime(program, basePacket, ROUTER_LIFETIME);
1560         verifyRaLifetime(program, newFlowLabelPacket, ROUTER_LIFETIME);
1561         verifyRaLifetime(program, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
1562         verifyRaLifetime(program, rdnssOptionPacket, RDNSS_LIFETIME);
1563         verifyRaLifetime(program, routeInfoOptionPacket, ROUTE_LIFETIME);
1564         verifyRaLifetime(program, dnsslOptionPacket, ROUTER_LIFETIME);
1565 
1566         apfFilter.shutdown();
1567     }
1568 
1569     /**
1570      * Stage a file for testing, i.e. make it native accessible. Given a resource ID,
1571      * copy that resource into the app's data directory and return the path to it.
1572      */
stageFile(int rawId)1573     private String stageFile(int rawId) throws Exception {
1574         File file = new File(InstrumentationRegistry.getContext().getFilesDir(), "staged_file");
1575         new File(file.getParent()).mkdirs();
1576         InputStream in = null;
1577         OutputStream out = null;
1578         try {
1579             in = InstrumentationRegistry.getContext().getResources().openRawResource(rawId);
1580             out = new FileOutputStream(file);
1581             Streams.copy(in, out);
1582         } finally {
1583             if (in != null) in.close();
1584             if (out != null) out.close();
1585         }
1586         return file.getAbsolutePath();
1587     }
1588 
put(ByteBuffer buffer, int position, byte[] bytes)1589     private static void put(ByteBuffer buffer, int position, byte[] bytes) {
1590         final int original = buffer.position();
1591         buffer.position(position);
1592         buffer.put(bytes);
1593         buffer.position(original);
1594     }
1595 
1596     @Test
testRaParsing()1597     public void testRaParsing() throws Exception {
1598         final int maxRandomPacketSize = 512;
1599         final Random r = new Random();
1600         MockIpClientCallback cb = new MockIpClientCallback();
1601         ApfConfiguration config = getDefaultConfig();
1602         config.multicastFilter = DROP_MULTICAST;
1603         config.ieee802_3Filter = DROP_802_3_FRAMES;
1604         TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog);
1605         for (int i = 0; i < 1000; i++) {
1606             byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
1607             r.nextBytes(packet);
1608             try {
1609                 apfFilter.new Ra(packet, packet.length);
1610             } catch (ApfFilter.InvalidRaException e) {
1611             } catch (Exception e) {
1612                 throw new Exception("bad packet: " + HexDump.toHexString(packet), e);
1613             }
1614         }
1615     }
1616 
1617     @Test
testRaProcessing()1618     public void testRaProcessing() throws Exception {
1619         final int maxRandomPacketSize = 512;
1620         final Random r = new Random();
1621         MockIpClientCallback cb = new MockIpClientCallback();
1622         ApfConfiguration config = getDefaultConfig();
1623         config.multicastFilter = DROP_MULTICAST;
1624         config.ieee802_3Filter = DROP_802_3_FRAMES;
1625         TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog);
1626         for (int i = 0; i < 1000; i++) {
1627             byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
1628             r.nextBytes(packet);
1629             try {
1630                 apfFilter.processRa(packet, packet.length);
1631             } catch (Exception e) {
1632                 throw new Exception("bad packet: " + HexDump.toHexString(packet), e);
1633             }
1634         }
1635     }
1636 
1637     /**
1638      * Call the APF interpreter to run {@code program} on {@code packet} with persistent memory
1639      * segment {@data} pretending the filter was installed {@code filter_age} seconds ago.
1640      */
apfSimulate(byte[] program, byte[] packet, byte[] data, int filter_age)1641     private native static int apfSimulate(byte[] program, byte[] packet, byte[] data,
1642         int filter_age);
1643 
1644     /**
1645      * Compile a tcpdump human-readable filter (e.g. "icmp" or "tcp port 54") into a BPF
1646      * prorgam and return a human-readable dump of the BPF program identical to "tcpdump -d".
1647      */
compileToBpf(String filter)1648     private native static String compileToBpf(String filter);
1649 
1650     /**
1651      * Open packet capture file {@code pcap_filename} and filter the packets using tcpdump
1652      * human-readable filter (e.g. "icmp" or "tcp port 54") compiled to a BPF program and
1653      * at the same time using APF program {@code apf_program}.  Return {@code true} if
1654      * both APF and BPF programs filter out exactly the same packets.
1655      */
compareBpfApf(String filter, String pcap_filename, byte[] apf_program)1656     private native static boolean compareBpfApf(String filter, String pcap_filename,
1657             byte[] apf_program);
1658 
1659     @Test
testBroadcastAddress()1660     public void testBroadcastAddress() throws Exception {
1661         assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 0));
1662         assertEqualsIp("0.0.0.0", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 32));
1663         assertEqualsIp("0.0.3.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 22));
1664         assertEqualsIp("0.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 8));
1665 
1666         assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 0));
1667         assertEqualsIp("10.0.0.1", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 32));
1668         assertEqualsIp("10.0.0.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 24));
1669         assertEqualsIp("10.0.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 16));
1670     }
1671 
assertEqualsIp(String expected, int got)1672     public void assertEqualsIp(String expected, int got) throws Exception {
1673         int want = bytesToBEInt(InetAddress.getByName(expected).getAddress());
1674         assertEquals(want, got);
1675     }
1676 }
1677