1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.net.apf;
18 
19 import static android.system.OsConstants.AF_UNIX;
20 import static android.system.OsConstants.ARPHRD_ETHER;
21 import static android.system.OsConstants.ETH_P_ARP;
22 import static android.system.OsConstants.ETH_P_IP;
23 import static android.system.OsConstants.ETH_P_IPV6;
24 import static android.system.OsConstants.IPPROTO_ICMPV6;
25 import static android.system.OsConstants.IPPROTO_TCP;
26 import static android.system.OsConstants.IPPROTO_UDP;
27 import static android.system.OsConstants.SOCK_STREAM;
28 
29 import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ECHO_REQUEST_TYPE;
30 import static com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_LEN;
31 
32 import static org.junit.Assert.assertEquals;
33 import static org.junit.Assert.assertFalse;
34 import static org.junit.Assert.assertTrue;
35 import static org.junit.Assert.fail;
36 import static org.mockito.Mockito.atLeastOnce;
37 import static org.mockito.Mockito.mock;
38 import static org.mockito.Mockito.verify;
39 
40 import android.content.Context;
41 import android.net.InetAddresses;
42 import android.net.IpPrefix;
43 import android.net.LinkAddress;
44 import android.net.LinkProperties;
45 import android.net.NattKeepalivePacketDataParcelable;
46 import android.net.TcpKeepalivePacketDataParcelable;
47 import android.net.apf.ApfFilter.ApfConfiguration;
48 import android.net.apf.ApfGenerator.IllegalInstructionException;
49 import android.net.apf.ApfGenerator.Register;
50 import android.net.ip.IIpClientCallbacks;
51 import android.net.ip.IpClient.IpClientCallbacksWrapper;
52 import android.net.metrics.IpConnectivityLog;
53 import android.net.metrics.RaEvent;
54 import android.net.util.InterfaceParams;
55 import android.net.util.SharedLog;
56 import android.os.ConditionVariable;
57 import android.os.Parcelable;
58 import android.os.SystemClock;
59 import android.system.ErrnoException;
60 import android.system.Os;
61 import android.text.format.DateUtils;
62 import android.util.Log;
63 
64 import androidx.test.InstrumentationRegistry;
65 import androidx.test.filters.SmallTest;
66 import androidx.test.runner.AndroidJUnit4;
67 
68 import com.android.internal.util.HexDump;
69 import com.android.net.module.util.Inet4AddressUtils;
70 import com.android.net.module.util.NetworkStackConstants;
71 import com.android.networkstack.apishim.NetworkInformationShimImpl;
72 import com.android.server.networkstack.tests.R;
73 
74 import libcore.io.IoUtils;
75 import libcore.io.Streams;
76 
77 import org.junit.Before;
78 import org.junit.Test;
79 import org.junit.runner.RunWith;
80 import org.mockito.ArgumentCaptor;
81 import org.mockito.Mock;
82 import org.mockito.MockitoAnnotations;
83 
84 import java.io.File;
85 import java.io.FileDescriptor;
86 import java.io.FileOutputStream;
87 import java.io.IOException;
88 import java.io.InputStream;
89 import java.io.OutputStream;
90 import java.net.Inet4Address;
91 import java.net.InetAddress;
92 import java.nio.ByteBuffer;
93 import java.util.Arrays;
94 import java.util.List;
95 import java.util.Random;
96 
97 /**
98  * Tests for APF program generator and interpreter.
99  *
100  * Build, install and run with:
101  *  runtest frameworks-net -c android.net.apf.ApfTest
102  */
103 @RunWith(AndroidJUnit4.class)
104 @SmallTest
105 public class ApfTest {
106     private static final int TIMEOUT_MS = 500;
107     private static final int MIN_APF_VERSION = 2;
108 
109     @Mock IpConnectivityLog mLog;
110     @Mock Context mContext;
111 
112     @Before
setUp()113     public void setUp() throws Exception {
114         MockitoAnnotations.initMocks(this);
115         // Load up native shared library containing APF interpreter exposed via JNI.
116         System.loadLibrary("networkstacktestsjni");
117     }
118 
119     private static final String TAG = "ApfTest";
120     // Expected return codes from APF interpreter.
121     private static final int PASS = 1;
122     private static final int DROP = 0;
123     // Interpreter will just accept packets without link layer headers, so pad fake packet to at
124     // least the minimum packet size.
125     private static final int MIN_PKT_SIZE = 15;
126 
127     private static final ApfCapabilities MOCK_APF_CAPABILITIES =
128             new ApfCapabilities(2, 4096, ARPHRD_ETHER);
129 
130     private static final boolean DROP_MULTICAST = true;
131     private static final boolean ALLOW_MULTICAST = false;
132 
133     private static final boolean DROP_802_3_FRAMES = true;
134     private static final boolean ALLOW_802_3_FRAMES = false;
135 
136     private static final int MIN_RDNSS_LIFETIME_SEC = 0;
137 
138     // Constants for opcode encoding
139     private static final byte LI_OP   = (byte)(13 << 3);
140     private static final byte LDDW_OP = (byte)(22 << 3);
141     private static final byte STDW_OP = (byte)(23 << 3);
142     private static final byte SIZE0   = (byte)(0 << 1);
143     private static final byte SIZE8   = (byte)(1 << 1);
144     private static final byte SIZE16  = (byte)(2 << 1);
145     private static final byte SIZE32  = (byte)(3 << 1);
146     private static final byte R1 = 1;
147 
getDefaultConfig()148     private static ApfConfiguration getDefaultConfig() {
149         ApfFilter.ApfConfiguration config = new ApfConfiguration();
150         config.apfCapabilities = MOCK_APF_CAPABILITIES;
151         config.multicastFilter = ALLOW_MULTICAST;
152         config.ieee802_3Filter = ALLOW_802_3_FRAMES;
153         config.ethTypeBlackList = new int[0];
154         config.minRdnssLifetimeSec = MIN_RDNSS_LIFETIME_SEC;
155         config.minRdnssLifetimeSec = 67;
156         return config;
157     }
158 
label(int code)159     private static String label(int code) {
160         switch (code) {
161             case PASS: return "PASS";
162             case DROP: return "DROP";
163             default:   return "UNKNOWN";
164         }
165     }
166 
assertReturnCodesEqual(int expected, int got)167     private static void assertReturnCodesEqual(int expected, int got) {
168         assertEquals(label(expected), label(got));
169     }
170 
assertVerdict(int expected, byte[] program, byte[] packet, int filterAge)171     private void assertVerdict(int expected, byte[] program, byte[] packet, int filterAge) {
172         assertReturnCodesEqual(expected, apfSimulate(program, packet, null, filterAge));
173     }
174 
assertVerdict(int expected, byte[] program, byte[] packet)175     private void assertVerdict(int expected, byte[] program, byte[] packet) {
176         assertReturnCodesEqual(expected, apfSimulate(program, packet, null, 0));
177     }
178 
assertPass(byte[] program, byte[] packet, int filterAge)179     private void assertPass(byte[] program, byte[] packet, int filterAge) {
180         assertVerdict(PASS, program, packet, filterAge);
181     }
182 
assertPass(byte[] program, byte[] packet)183     private void assertPass(byte[] program, byte[] packet) {
184         assertVerdict(PASS, program, packet);
185     }
186 
assertDrop(byte[] program, byte[] packet, int filterAge)187     private void assertDrop(byte[] program, byte[] packet, int filterAge) {
188         assertVerdict(DROP, program, packet, filterAge);
189     }
190 
assertDrop(byte[] program, byte[] packet)191     private void assertDrop(byte[] program, byte[] packet) {
192         assertVerdict(DROP, program, packet);
193     }
194 
assertProgramEquals(byte[] expected, byte[] program)195     private void assertProgramEquals(byte[] expected, byte[] program) throws AssertionError {
196         // assertArrayEquals() would only print one byte, making debugging difficult.
197         if (!Arrays.equals(expected, program)) {
198             throw new AssertionError(
199                     "\nexpected: " + HexDump.toHexString(expected) +
200                     "\nactual:   " + HexDump.toHexString(program));
201         }
202     }
203 
assertDataMemoryContents( int expected, byte[] program, byte[] packet, byte[] data, byte[] expected_data)204     private void assertDataMemoryContents(
205             int expected, byte[] program, byte[] packet, byte[] data, byte[] expected_data)
206             throws IllegalInstructionException, Exception {
207         assertReturnCodesEqual(expected, apfSimulate(program, packet, data, 0 /* filterAge */));
208 
209         // assertArrayEquals() would only print one byte, making debugging difficult.
210         if (!Arrays.equals(expected_data, data)) {
211             throw new Exception(
212                     "\nprogram:     " + HexDump.toHexString(program) +
213                     "\ndata memory: " + HexDump.toHexString(data) +
214                     "\nexpected:    " + HexDump.toHexString(expected_data));
215         }
216     }
217 
assertVerdict(int expected, ApfGenerator gen, byte[] packet, int filterAge)218     private void assertVerdict(int expected, ApfGenerator gen, byte[] packet, int filterAge)
219             throws IllegalInstructionException {
220         assertReturnCodesEqual(expected, apfSimulate(gen.generate(), packet, null,
221               filterAge));
222     }
223 
assertPass(ApfGenerator gen, byte[] packet, int filterAge)224     private void assertPass(ApfGenerator gen, byte[] packet, int filterAge)
225             throws IllegalInstructionException {
226         assertVerdict(PASS, gen, packet, filterAge);
227     }
228 
assertDrop(ApfGenerator gen, byte[] packet, int filterAge)229     private void assertDrop(ApfGenerator gen, byte[] packet, int filterAge)
230             throws IllegalInstructionException {
231         assertVerdict(DROP, gen, packet, filterAge);
232     }
233 
assertPass(ApfGenerator gen)234     private void assertPass(ApfGenerator gen)
235             throws IllegalInstructionException {
236         assertVerdict(PASS, gen, new byte[MIN_PKT_SIZE], 0);
237     }
238 
assertDrop(ApfGenerator gen)239     private void assertDrop(ApfGenerator gen)
240             throws IllegalInstructionException {
241         assertVerdict(DROP, gen, new byte[MIN_PKT_SIZE], 0);
242     }
243 
244     /**
245      * Test each instruction by generating a program containing the instruction,
246      * generating bytecode for that program and running it through the
247      * interpreter to verify it functions correctly.
248      */
249     @Test
testApfInstructions()250     public void testApfInstructions() throws IllegalInstructionException {
251         // Empty program should pass because having the program counter reach the
252         // location immediately after the program indicates the packet should be
253         // passed to the AP.
254         ApfGenerator gen = new ApfGenerator(MIN_APF_VERSION);
255         assertPass(gen);
256 
257         // Test jumping to pass label.
258         gen = new ApfGenerator(MIN_APF_VERSION);
259         gen.addJump(gen.PASS_LABEL);
260         byte[] program = gen.generate();
261         assertEquals(1, program.length);
262         assertEquals((14 << 3) | (0 << 1) | 0, program[0]);
263         assertPass(program, new byte[MIN_PKT_SIZE], 0);
264 
265         // Test jumping to drop label.
266         gen = new ApfGenerator(MIN_APF_VERSION);
267         gen.addJump(gen.DROP_LABEL);
268         program = gen.generate();
269         assertEquals(2, program.length);
270         assertEquals((14 << 3) | (1 << 1) | 0, program[0]);
271         assertEquals(1, program[1]);
272         assertDrop(program, new byte[15], 15);
273 
274         // Test jumping if equal to 0.
275         gen = new ApfGenerator(MIN_APF_VERSION);
276         gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
277         assertDrop(gen);
278 
279         // Test jumping if not equal to 0.
280         gen = new ApfGenerator(MIN_APF_VERSION);
281         gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL);
282         assertPass(gen);
283         gen = new ApfGenerator(MIN_APF_VERSION);
284         gen.addLoadImmediate(Register.R0, 1);
285         gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL);
286         assertDrop(gen);
287 
288         // Test jumping if registers equal.
289         gen = new ApfGenerator(MIN_APF_VERSION);
290         gen.addJumpIfR0EqualsR1(gen.DROP_LABEL);
291         assertDrop(gen);
292 
293         // Test jumping if registers not equal.
294         gen = new ApfGenerator(MIN_APF_VERSION);
295         gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL);
296         assertPass(gen);
297         gen = new ApfGenerator(MIN_APF_VERSION);
298         gen.addLoadImmediate(Register.R0, 1);
299         gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL);
300         assertDrop(gen);
301 
302         // Test load immediate.
303         gen = new ApfGenerator(MIN_APF_VERSION);
304         gen.addLoadImmediate(Register.R0, 1234567890);
305         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
306         assertDrop(gen);
307 
308         // Test add.
309         gen = new ApfGenerator(MIN_APF_VERSION);
310         gen.addAdd(1234567890);
311         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
312         assertDrop(gen);
313 
314         // Test subtract.
315         gen = new ApfGenerator(MIN_APF_VERSION);
316         gen.addAdd(-1234567890);
317         gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
318         assertDrop(gen);
319 
320         // Test or.
321         gen = new ApfGenerator(MIN_APF_VERSION);
322         gen.addOr(1234567890);
323         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
324         assertDrop(gen);
325 
326         // Test and.
327         gen = new ApfGenerator(MIN_APF_VERSION);
328         gen.addLoadImmediate(Register.R0, 1234567890);
329         gen.addAnd(123456789);
330         gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL);
331         assertDrop(gen);
332 
333         // Test left shift.
334         gen = new ApfGenerator(MIN_APF_VERSION);
335         gen.addLoadImmediate(Register.R0, 1234567890);
336         gen.addLeftShift(1);
337         gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL);
338         assertDrop(gen);
339 
340         // Test right shift.
341         gen = new ApfGenerator(MIN_APF_VERSION);
342         gen.addLoadImmediate(Register.R0, 1234567890);
343         gen.addRightShift(1);
344         gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL);
345         assertDrop(gen);
346 
347         // Test multiply.
348         gen = new ApfGenerator(MIN_APF_VERSION);
349         gen.addLoadImmediate(Register.R0, 123456789);
350         gen.addMul(2);
351         gen.addJumpIfR0Equals(123456789 * 2, gen.DROP_LABEL);
352         assertDrop(gen);
353 
354         // Test divide.
355         gen = new ApfGenerator(MIN_APF_VERSION);
356         gen.addLoadImmediate(Register.R0, 1234567890);
357         gen.addDiv(2);
358         gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL);
359         assertDrop(gen);
360 
361         // Test divide by zero.
362         gen = new ApfGenerator(MIN_APF_VERSION);
363         gen.addDiv(0);
364         gen.addJump(gen.DROP_LABEL);
365         assertPass(gen);
366 
367         // Test add.
368         gen = new ApfGenerator(MIN_APF_VERSION);
369         gen.addLoadImmediate(Register.R1, 1234567890);
370         gen.addAddR1();
371         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
372         assertDrop(gen);
373 
374         // Test subtract.
375         gen = new ApfGenerator(MIN_APF_VERSION);
376         gen.addLoadImmediate(Register.R1, -1234567890);
377         gen.addAddR1();
378         gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
379         assertDrop(gen);
380 
381         // Test or.
382         gen = new ApfGenerator(MIN_APF_VERSION);
383         gen.addLoadImmediate(Register.R1, 1234567890);
384         gen.addOrR1();
385         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
386         assertDrop(gen);
387 
388         // Test and.
389         gen = new ApfGenerator(MIN_APF_VERSION);
390         gen.addLoadImmediate(Register.R0, 1234567890);
391         gen.addLoadImmediate(Register.R1, 123456789);
392         gen.addAndR1();
393         gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL);
394         assertDrop(gen);
395 
396         // Test left shift.
397         gen = new ApfGenerator(MIN_APF_VERSION);
398         gen.addLoadImmediate(Register.R0, 1234567890);
399         gen.addLoadImmediate(Register.R1, 1);
400         gen.addLeftShiftR1();
401         gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL);
402         assertDrop(gen);
403 
404         // Test right shift.
405         gen = new ApfGenerator(MIN_APF_VERSION);
406         gen.addLoadImmediate(Register.R0, 1234567890);
407         gen.addLoadImmediate(Register.R1, -1);
408         gen.addLeftShiftR1();
409         gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL);
410         assertDrop(gen);
411 
412         // Test multiply.
413         gen = new ApfGenerator(MIN_APF_VERSION);
414         gen.addLoadImmediate(Register.R0, 123456789);
415         gen.addLoadImmediate(Register.R1, 2);
416         gen.addMulR1();
417         gen.addJumpIfR0Equals(123456789 * 2, gen.DROP_LABEL);
418         assertDrop(gen);
419 
420         // Test divide.
421         gen = new ApfGenerator(MIN_APF_VERSION);
422         gen.addLoadImmediate(Register.R0, 1234567890);
423         gen.addLoadImmediate(Register.R1, 2);
424         gen.addDivR1();
425         gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL);
426         assertDrop(gen);
427 
428         // Test divide by zero.
429         gen = new ApfGenerator(MIN_APF_VERSION);
430         gen.addDivR1();
431         gen.addJump(gen.DROP_LABEL);
432         assertPass(gen);
433 
434         // Test byte load.
435         gen = new ApfGenerator(MIN_APF_VERSION);
436         gen.addLoad8(Register.R0, 1);
437         gen.addJumpIfR0Equals(45, gen.DROP_LABEL);
438         assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
439 
440         // Test out of bounds load.
441         gen = new ApfGenerator(MIN_APF_VERSION);
442         gen.addLoad8(Register.R0, 16);
443         gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
444         assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
445 
446         // Test half-word load.
447         gen = new ApfGenerator(MIN_APF_VERSION);
448         gen.addLoad16(Register.R0, 1);
449         gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL);
450         assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
451 
452         // Test word load.
453         gen = new ApfGenerator(MIN_APF_VERSION);
454         gen.addLoad32(Register.R0, 1);
455         gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL);
456         assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0);
457 
458         // Test byte indexed load.
459         gen = new ApfGenerator(MIN_APF_VERSION);
460         gen.addLoadImmediate(Register.R1, 1);
461         gen.addLoad8Indexed(Register.R0, 0);
462         gen.addJumpIfR0Equals(45, gen.DROP_LABEL);
463         assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
464 
465         // Test out of bounds indexed load.
466         gen = new ApfGenerator(MIN_APF_VERSION);
467         gen.addLoadImmediate(Register.R1, 8);
468         gen.addLoad8Indexed(Register.R0, 8);
469         gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
470         assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
471 
472         // Test half-word indexed load.
473         gen = new ApfGenerator(MIN_APF_VERSION);
474         gen.addLoadImmediate(Register.R1, 1);
475         gen.addLoad16Indexed(Register.R0, 0);
476         gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL);
477         assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
478 
479         // Test word indexed load.
480         gen = new ApfGenerator(MIN_APF_VERSION);
481         gen.addLoadImmediate(Register.R1, 1);
482         gen.addLoad32Indexed(Register.R0, 0);
483         gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL);
484         assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0);
485 
486         // Test jumping if greater than.
487         gen = new ApfGenerator(MIN_APF_VERSION);
488         gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL);
489         assertPass(gen);
490         gen = new ApfGenerator(MIN_APF_VERSION);
491         gen.addLoadImmediate(Register.R0, 1);
492         gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL);
493         assertDrop(gen);
494 
495         // Test jumping if less than.
496         gen = new ApfGenerator(MIN_APF_VERSION);
497         gen.addJumpIfR0LessThan(0, gen.DROP_LABEL);
498         assertPass(gen);
499         gen = new ApfGenerator(MIN_APF_VERSION);
500         gen.addJumpIfR0LessThan(1, gen.DROP_LABEL);
501         assertDrop(gen);
502 
503         // Test jumping if any bits set.
504         gen = new ApfGenerator(MIN_APF_VERSION);
505         gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
506         assertPass(gen);
507         gen = new ApfGenerator(MIN_APF_VERSION);
508         gen.addLoadImmediate(Register.R0, 1);
509         gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
510         assertDrop(gen);
511         gen = new ApfGenerator(MIN_APF_VERSION);
512         gen.addLoadImmediate(Register.R0, 3);
513         gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
514         assertDrop(gen);
515 
516         // Test jumping if register greater than.
517         gen = new ApfGenerator(MIN_APF_VERSION);
518         gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL);
519         assertPass(gen);
520         gen = new ApfGenerator(MIN_APF_VERSION);
521         gen.addLoadImmediate(Register.R0, 2);
522         gen.addLoadImmediate(Register.R1, 1);
523         gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL);
524         assertDrop(gen);
525 
526         // Test jumping if register less than.
527         gen = new ApfGenerator(MIN_APF_VERSION);
528         gen.addJumpIfR0LessThanR1(gen.DROP_LABEL);
529         assertPass(gen);
530         gen = new ApfGenerator(MIN_APF_VERSION);
531         gen.addLoadImmediate(Register.R1, 1);
532         gen.addJumpIfR0LessThanR1(gen.DROP_LABEL);
533         assertDrop(gen);
534 
535         // Test jumping if any bits set in register.
536         gen = new ApfGenerator(MIN_APF_VERSION);
537         gen.addLoadImmediate(Register.R1, 3);
538         gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
539         assertPass(gen);
540         gen = new ApfGenerator(MIN_APF_VERSION);
541         gen.addLoadImmediate(Register.R1, 3);
542         gen.addLoadImmediate(Register.R0, 1);
543         gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
544         assertDrop(gen);
545         gen = new ApfGenerator(MIN_APF_VERSION);
546         gen.addLoadImmediate(Register.R1, 3);
547         gen.addLoadImmediate(Register.R0, 3);
548         gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
549         assertDrop(gen);
550 
551         // Test load from memory.
552         gen = new ApfGenerator(MIN_APF_VERSION);
553         gen.addLoadFromMemory(Register.R0, 0);
554         gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
555         assertDrop(gen);
556 
557         // Test store to memory.
558         gen = new ApfGenerator(MIN_APF_VERSION);
559         gen.addLoadImmediate(Register.R1, 1234567890);
560         gen.addStoreToMemory(Register.R1, 12);
561         gen.addLoadFromMemory(Register.R0, 12);
562         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
563         assertDrop(gen);
564 
565         // Test filter age pre-filled memory.
566         gen = new ApfGenerator(MIN_APF_VERSION);
567         gen.addLoadFromMemory(Register.R0, gen.FILTER_AGE_MEMORY_SLOT);
568         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
569         assertDrop(gen, new byte[MIN_PKT_SIZE], 1234567890);
570 
571         // Test packet size pre-filled memory.
572         gen = new ApfGenerator(MIN_APF_VERSION);
573         gen.addLoadFromMemory(Register.R0, gen.PACKET_SIZE_MEMORY_SLOT);
574         gen.addJumpIfR0Equals(MIN_PKT_SIZE, gen.DROP_LABEL);
575         assertDrop(gen);
576 
577         // Test IPv4 header size pre-filled memory.
578         gen = new ApfGenerator(MIN_APF_VERSION);
579         gen.addLoadFromMemory(Register.R0, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
580         gen.addJumpIfR0Equals(20, gen.DROP_LABEL);
581         assertDrop(gen, new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x45}, 0);
582 
583         // Test not.
584         gen = new ApfGenerator(MIN_APF_VERSION);
585         gen.addLoadImmediate(Register.R0, 1234567890);
586         gen.addNot(Register.R0);
587         gen.addJumpIfR0Equals(~1234567890, gen.DROP_LABEL);
588         assertDrop(gen);
589 
590         // Test negate.
591         gen = new ApfGenerator(MIN_APF_VERSION);
592         gen.addLoadImmediate(Register.R0, 1234567890);
593         gen.addNeg(Register.R0);
594         gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
595         assertDrop(gen);
596 
597         // Test move.
598         gen = new ApfGenerator(MIN_APF_VERSION);
599         gen.addLoadImmediate(Register.R1, 1234567890);
600         gen.addMove(Register.R0);
601         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
602         assertDrop(gen);
603         gen = new ApfGenerator(MIN_APF_VERSION);
604         gen.addLoadImmediate(Register.R0, 1234567890);
605         gen.addMove(Register.R1);
606         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
607         assertDrop(gen);
608 
609         // Test swap.
610         gen = new ApfGenerator(MIN_APF_VERSION);
611         gen.addLoadImmediate(Register.R1, 1234567890);
612         gen.addSwap();
613         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
614         assertDrop(gen);
615         gen = new ApfGenerator(MIN_APF_VERSION);
616         gen.addLoadImmediate(Register.R0, 1234567890);
617         gen.addSwap();
618         gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
619         assertDrop(gen);
620 
621         // Test jump if bytes not equal.
622         gen = new ApfGenerator(MIN_APF_VERSION);
623         gen.addLoadImmediate(Register.R0, 1);
624         gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
625         program = gen.generate();
626         assertEquals(6, program.length);
627         assertEquals((13 << 3) | (1 << 1) | 0, program[0]);
628         assertEquals(1, program[1]);
629         assertEquals(((20 << 3) | (1 << 1) | 0) - 256, program[2]);
630         assertEquals(1, program[3]);
631         assertEquals(1, program[4]);
632         assertEquals(123, program[5]);
633         assertDrop(program, new byte[MIN_PKT_SIZE], 0);
634         gen = new ApfGenerator(MIN_APF_VERSION);
635         gen.addLoadImmediate(Register.R0, 1);
636         gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
637         byte[] packet123 = {0,123,0,0,0,0,0,0,0,0,0,0,0,0,0};
638         assertPass(gen, packet123, 0);
639         gen = new ApfGenerator(MIN_APF_VERSION);
640         gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
641         assertDrop(gen, packet123, 0);
642         gen = new ApfGenerator(MIN_APF_VERSION);
643         gen.addLoadImmediate(Register.R0, 1);
644         gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,30,4,5}, gen.DROP_LABEL);
645         byte[] packet12345 = {0,1,2,3,4,5,0,0,0,0,0,0,0,0,0};
646         assertDrop(gen, packet12345, 0);
647         gen = new ApfGenerator(MIN_APF_VERSION);
648         gen.addLoadImmediate(Register.R0, 1);
649         gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,3,4,5}, gen.DROP_LABEL);
650         assertPass(gen, packet12345, 0);
651     }
652 
653     @Test(expected = ApfGenerator.IllegalInstructionException.class)
testApfGeneratorWantsV2OrGreater()654     public void testApfGeneratorWantsV2OrGreater() throws Exception {
655         // The minimum supported APF version is 2.
656         new ApfGenerator(1);
657     }
658 
659     @Test
testApfDataOpcodesWantApfV3()660     public void testApfDataOpcodesWantApfV3() throws IllegalInstructionException, Exception {
661         ApfGenerator gen = new ApfGenerator(MIN_APF_VERSION);
662         try {
663             gen.addStoreData(Register.R0, 0);
664             fail();
665         } catch (IllegalInstructionException expected) {
666             /* pass */
667         }
668         try {
669             gen.addLoadData(Register.R0, 0);
670             fail();
671         } catch (IllegalInstructionException expected) {
672             /* pass */
673         }
674     }
675 
676     /**
677      * Test that the generator emits immediates using the shortest possible encoding.
678      */
679     @Test
testImmediateEncoding()680     public void testImmediateEncoding() throws IllegalInstructionException {
681         ApfGenerator gen;
682 
683         // 0-byte immediate: li R0, 0
684         gen = new ApfGenerator(4);
685         gen.addLoadImmediate(Register.R0, 0);
686         assertProgramEquals(new byte[]{LI_OP | SIZE0}, gen.generate());
687 
688         // 1-byte immediate: li R0, 42
689         gen = new ApfGenerator(4);
690         gen.addLoadImmediate(Register.R0, 42);
691         assertProgramEquals(new byte[]{LI_OP | SIZE8, 42}, gen.generate());
692 
693         // 2-byte immediate: li R1, 0x1234
694         gen = new ApfGenerator(4);
695         gen.addLoadImmediate(Register.R1, 0x1234);
696         assertProgramEquals(new byte[]{LI_OP | SIZE16 | R1, 0x12, 0x34}, gen.generate());
697 
698         // 4-byte immediate: li R0, 0x12345678
699         gen = new ApfGenerator(3);
700         gen.addLoadImmediate(Register.R0, 0x12345678);
701         assertProgramEquals(
702                 new byte[]{LI_OP | SIZE32, 0x12, 0x34, 0x56, 0x78},
703                 gen.generate());
704     }
705 
706     /**
707      * Test that the generator emits negative immediates using the shortest possible encoding.
708      */
709     @Test
testNegativeImmediateEncoding()710     public void testNegativeImmediateEncoding() throws IllegalInstructionException {
711         ApfGenerator gen;
712 
713         // 1-byte negative immediate: li R0, -42
714         gen = new ApfGenerator(3);
715         gen.addLoadImmediate(Register.R0, -42);
716         assertProgramEquals(new byte[]{LI_OP | SIZE8, -42}, gen.generate());
717 
718         // 2-byte negative immediate: li R1, -0x1122
719         gen = new ApfGenerator(3);
720         gen.addLoadImmediate(Register.R1, -0x1122);
721         assertProgramEquals(new byte[]{LI_OP | SIZE16 | R1, (byte)0xEE, (byte)0xDE},
722                 gen.generate());
723 
724         // 4-byte negative immediate: li R0, -0x11223344
725         gen = new ApfGenerator(3);
726         gen.addLoadImmediate(Register.R0, -0x11223344);
727         assertProgramEquals(
728                 new byte[]{LI_OP | SIZE32, (byte)0xEE, (byte)0xDD, (byte)0xCC, (byte)0xBC},
729                 gen.generate());
730     }
731 
732     /**
733      * Test that the generator correctly emits positive and negative immediates for LDDW/STDW.
734      */
735     @Test
testLoadStoreDataEncoding()736     public void testLoadStoreDataEncoding() throws IllegalInstructionException {
737         ApfGenerator gen;
738 
739         // Load data with no offset: lddw R0, [0 + r1]
740         gen = new ApfGenerator(3);
741         gen.addLoadData(Register.R0, 0);
742         assertProgramEquals(new byte[]{LDDW_OP | SIZE0}, gen.generate());
743 
744         // Store data with 8bit negative offset: lddw r0, [-42 + r1]
745         gen = new ApfGenerator(3);
746         gen.addStoreData(Register.R0, -42);
747         assertProgramEquals(new byte[]{STDW_OP | SIZE8, -42}, gen.generate());
748 
749         // Store data to R1 with 16bit negative offset: stdw r1, [-0x1122 + r0]
750         gen = new ApfGenerator(3);
751         gen.addStoreData(Register.R1, -0x1122);
752         assertProgramEquals(new byte[]{STDW_OP | SIZE16 | R1, (byte)0xEE, (byte)0xDE},
753                 gen.generate());
754 
755         // Load data to R1 with 32bit negative offset: lddw r1, [0xDEADBEEF + r0]
756         gen = new ApfGenerator(3);
757         gen.addLoadData(Register.R1, 0xDEADBEEF);
758         assertProgramEquals(
759                 new byte[]{LDDW_OP | SIZE32 | R1, (byte)0xDE, (byte)0xAD, (byte)0xBE, (byte)0xEF},
760                 gen.generate());
761     }
762 
763     /**
764      * Test that the interpreter correctly executes STDW with a negative 8bit offset
765      */
766     @Test
testApfDataWrite()767     public void testApfDataWrite() throws IllegalInstructionException, Exception {
768         byte[] packet = new byte[MIN_PKT_SIZE];
769         byte[] data = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
770         byte[] expected_data = data.clone();
771 
772         // No memory access instructions: should leave the data segment untouched.
773         ApfGenerator gen = new ApfGenerator(3);
774         assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
775 
776         // Expect value 0x87654321 to be stored starting from address -11 from the end of the
777         // data buffer, in big-endian order.
778         gen = new ApfGenerator(3);
779         gen.addLoadImmediate(Register.R0, 0x87654321);
780         gen.addLoadImmediate(Register.R1, -5);
781         gen.addStoreData(Register.R0, -6);  // -5 + -6 = -11 (offset +5 with data_len=16)
782         expected_data[5] = (byte)0x87;
783         expected_data[6] = (byte)0x65;
784         expected_data[7] = (byte)0x43;
785         expected_data[8] = (byte)0x21;
786         assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
787     }
788 
789     /**
790      * Test that the interpreter correctly executes LDDW with a negative 16bit offset
791      */
792     @Test
testApfDataRead()793     public void testApfDataRead() throws IllegalInstructionException, Exception {
794         // Program that DROPs if address 10 (-6) contains 0x87654321.
795         ApfGenerator gen = new ApfGenerator(3);
796         gen.addLoadImmediate(Register.R1, 1000);
797         gen.addLoadData(Register.R0, -1006);  // 1000 + -1006 = -6 (offset +10 with data_len=16)
798         gen.addJumpIfR0Equals(0x87654321, gen.DROP_LABEL);
799         byte[] program = gen.generate();
800         byte[] packet = new byte[MIN_PKT_SIZE];
801 
802         // Content is incorrect (last byte does not match) -> PASS
803         byte[] data = new byte[16];
804         data[10] = (byte)0x87;
805         data[11] = (byte)0x65;
806         data[12] = (byte)0x43;
807         data[13] = (byte)0x00;  // != 0x21
808         byte[] expected_data = data.clone();
809         assertDataMemoryContents(PASS, program, packet, data, expected_data);
810 
811         // Fix the last byte -> conditional jump taken -> DROP
812         data[13] = (byte)0x21;
813         expected_data = data;
814         assertDataMemoryContents(DROP, program, packet, data, expected_data);
815     }
816 
817     /**
818      * Test that the interpreter correctly executes LDDW followed by a STDW.
819      * To cover a few more edge cases, LDDW has a 0bit offset, while STDW has a positive 8bit
820      * offset.
821      */
822     @Test
testApfDataReadModifyWrite()823     public void testApfDataReadModifyWrite() throws IllegalInstructionException, Exception {
824         ApfGenerator gen = new ApfGenerator(3);
825         gen.addLoadImmediate(Register.R1, -22);
826         gen.addLoadData(Register.R0, 0);  // Load from address 32 -22 + 0 = 10
827         gen.addAdd(0x78453412);  // 87654321 + 78453412 = FFAA7733
828         gen.addStoreData(Register.R0, 4);  // Write back to address 32 -22 + 4 = 14
829 
830         byte[] packet = new byte[MIN_PKT_SIZE];
831         byte[] data = new byte[32];
832         data[10] = (byte)0x87;
833         data[11] = (byte)0x65;
834         data[12] = (byte)0x43;
835         data[13] = (byte)0x21;
836         byte[] expected_data = data.clone();
837         expected_data[14] = (byte)0xFF;
838         expected_data[15] = (byte)0xAA;
839         expected_data[16] = (byte)0x77;
840         expected_data[17] = (byte)0x33;
841         assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
842     }
843 
844     @Test
testApfDataBoundChecking()845     public void testApfDataBoundChecking() throws IllegalInstructionException, Exception {
846         byte[] packet = new byte[MIN_PKT_SIZE];
847         byte[] data = new byte[32];
848         byte[] expected_data = data;
849 
850         // Program that DROPs unconditionally. This is our the baseline.
851         ApfGenerator gen = new ApfGenerator(3);
852         gen.addLoadImmediate(Register.R0, 3);
853         gen.addLoadData(Register.R1, 7);
854         gen.addJump(gen.DROP_LABEL);
855         assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data);
856 
857         // Same program as before, but this time we're trying to load past the end of the data.
858         gen = new ApfGenerator(3);
859         gen.addLoadImmediate(Register.R0, 20);
860         gen.addLoadData(Register.R1, 15);  // 20 + 15 > 32
861         gen.addJump(gen.DROP_LABEL);  // Not reached.
862         assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
863 
864         // Subtracting an immediate should work...
865         gen = new ApfGenerator(3);
866         gen.addLoadImmediate(Register.R0, 20);
867         gen.addLoadData(Register.R1, -4);
868         gen.addJump(gen.DROP_LABEL);
869         assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data);
870 
871         // ...and underflowing simply wraps around to the end of the buffer...
872         gen = new ApfGenerator(3);
873         gen.addLoadImmediate(Register.R0, 20);
874         gen.addLoadData(Register.R1, -30);
875         gen.addJump(gen.DROP_LABEL);
876         assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data);
877 
878         // ...but doesn't allow accesses before the start of the buffer
879         gen = new ApfGenerator(3);
880         gen.addLoadImmediate(Register.R0, 20);
881         gen.addLoadData(Register.R1, -1000);
882         gen.addJump(gen.DROP_LABEL);  // Not reached.
883         assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
884     }
885 
886     /**
887      * Generate some BPF programs, translate them to APF, then run APF and BPF programs
888      * over packet traces and verify both programs filter out the same packets.
889      */
890     @Test
testApfAgainstBpf()891     public void testApfAgainstBpf() throws Exception {
892         String[] tcpdump_filters = new String[]{ "udp", "tcp", "icmp", "icmp6", "udp port 53",
893                 "arp", "dst 239.255.255.250", "arp or tcp or udp port 53", "net 192.168.1.0/24",
894                 "arp or icmp6 or portrange 53-54", "portrange 53-54 or portrange 100-50000",
895                 "tcp[tcpflags] & (tcp-ack|tcp-fin) != 0 and (ip[2:2] > 57 or icmp)" };
896         String pcap_filename = stageFile(R.raw.apf);
897         for (String tcpdump_filter : tcpdump_filters) {
898             byte[] apf_program = Bpf2Apf.convert(compileToBpf(tcpdump_filter));
899             assertTrue("Failed to match for filter: " + tcpdump_filter,
900                     compareBpfApf(tcpdump_filter, pcap_filename, apf_program));
901         }
902     }
903 
904     /**
905      * Generate APF program, run pcap file though APF filter, then check all the packets in the file
906      * should be dropped.
907      */
908     @Test
testApfFilterPcapFile()909     public void testApfFilterPcapFile() throws Exception {
910         final byte[] MOCK_PCAP_IPV4_ADDR = {(byte) 172, 16, 7, (byte) 151};
911         String pcapFilename = stageFile(R.raw.apfPcap);
912         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
913         LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_PCAP_IPV4_ADDR), 16);
914         LinkProperties lp = new LinkProperties();
915         lp.addLinkAddress(link);
916 
917         ApfConfiguration config = getDefaultConfig();
918         ApfCapabilities MOCK_APF_PCAP_CAPABILITIES = new ApfCapabilities(4, 1700, ARPHRD_ETHER);
919         config.apfCapabilities = MOCK_APF_PCAP_CAPABILITIES;
920         config.multicastFilter = DROP_MULTICAST;
921         config.ieee802_3Filter = DROP_802_3_FRAMES;
922         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
923         apfFilter.setLinkProperties(lp);
924         byte[] program = ipClientCallback.getApfProgram();
925         byte[] data = new byte[ApfFilter.Counter.totalSize()];
926         final boolean result;
927 
928         result = dropsAllPackets(program, data, pcapFilename);
929         Log.i(TAG, "testApfFilterPcapFile(): Data counters: " + HexDump.toHexString(data, false));
930 
931         assertTrue("Failed to drop all packets by filter. \nAPF counters:" +
932             HexDump.toHexString(data, false), result);
933     }
934 
935     private class MockIpClientCallback extends IpClientCallbacksWrapper {
936         private final ConditionVariable mGotApfProgram = new ConditionVariable();
937         private byte[] mLastApfProgram;
938 
MockIpClientCallback()939         MockIpClientCallback() {
940             super(mock(IIpClientCallbacks.class), mock(SharedLog.class),
941                     NetworkInformationShimImpl.newInstance());
942         }
943 
944         @Override
installPacketFilter(byte[] filter)945         public void installPacketFilter(byte[] filter) {
946             mLastApfProgram = filter;
947             mGotApfProgram.open();
948         }
949 
resetApfProgramWait()950         public void resetApfProgramWait() {
951             mGotApfProgram.close();
952         }
953 
getApfProgram()954         public byte[] getApfProgram() {
955             assertTrue(mGotApfProgram.block(TIMEOUT_MS));
956             return mLastApfProgram;
957         }
958 
assertNoProgramUpdate()959         public void assertNoProgramUpdate() {
960             assertFalse(mGotApfProgram.block(TIMEOUT_MS));
961         }
962     }
963 
964     private static class TestApfFilter extends ApfFilter {
965         public static final byte[] MOCK_MAC_ADDR = {1,2,3,4,5,6};
966 
967         private FileDescriptor mWriteSocket;
968         private final long mFixedTimeMs = SystemClock.elapsedRealtime();
969 
TestApfFilter(Context context, ApfConfiguration config, IpClientCallbacksWrapper ipClientCallback, IpConnectivityLog log)970         public TestApfFilter(Context context, ApfConfiguration config,
971                 IpClientCallbacksWrapper ipClientCallback, IpConnectivityLog log) throws Exception {
972             super(context, config, InterfaceParams.getByName("lo"), ipClientCallback, log);
973         }
974 
975         // Pretend an RA packet has been received and show it to ApfFilter.
pretendPacketReceived(byte[] packet)976         public void pretendPacketReceived(byte[] packet) throws IOException, ErrnoException {
977             // ApfFilter's ReceiveThread will be waiting to read this.
978             Os.write(mWriteSocket, packet, 0, packet.length);
979         }
980 
981         @Override
currentTimeSeconds()982         protected long currentTimeSeconds() {
983             return mFixedTimeMs / DateUtils.SECOND_IN_MILLIS;
984         }
985 
986         @Override
maybeStartFilter()987         void maybeStartFilter() {
988             mHardwareAddress = MOCK_MAC_ADDR;
989             installNewProgramLocked();
990 
991             // Create two sockets, "readSocket" and "mWriteSocket" and connect them together.
992             FileDescriptor readSocket = new FileDescriptor();
993             mWriteSocket = new FileDescriptor();
994             try {
995                 Os.socketpair(AF_UNIX, SOCK_STREAM, 0, mWriteSocket, readSocket);
996             } catch (ErrnoException e) {
997                 fail();
998                 return;
999             }
1000             // Now pass readSocket to ReceiveThread as if it was setup to read raw RAs.
1001             // This allows us to pretend RA packets have been recieved via pretendPacketReceived().
1002             mReceiveThread = new ReceiveThread(readSocket);
1003             mReceiveThread.start();
1004         }
1005 
1006         @Override
shutdown()1007         public void shutdown() {
1008             super.shutdown();
1009             IoUtils.closeQuietly(mWriteSocket);
1010         }
1011     }
1012 
1013     private static final int ETH_HEADER_LEN               = 14;
1014     private static final int ETH_DEST_ADDR_OFFSET         = 0;
1015     private static final int ETH_ETHERTYPE_OFFSET         = 12;
1016     private static final byte[] ETH_BROADCAST_MAC_ADDRESS =
1017             {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
1018 
1019     private static final int IP_HEADER_OFFSET = ETH_HEADER_LEN;
1020 
1021     private static final int IPV4_HEADER_LEN          = 20;
1022     private static final int IPV4_TOTAL_LENGTH_OFFSET = IP_HEADER_OFFSET + 2;
1023     private static final int IPV4_PROTOCOL_OFFSET     = IP_HEADER_OFFSET + 9;
1024     private static final int IPV4_SRC_ADDR_OFFSET     = IP_HEADER_OFFSET + 12;
1025     private static final int IPV4_DEST_ADDR_OFFSET    = IP_HEADER_OFFSET + 16;
1026 
1027     private static final int IPV4_TCP_HEADER_LEN           = 20;
1028     private static final int IPV4_TCP_HEADER_OFFSET        = IP_HEADER_OFFSET + IPV4_HEADER_LEN;
1029     private static final int IPV4_TCP_SRC_PORT_OFFSET      = IPV4_TCP_HEADER_OFFSET + 0;
1030     private static final int IPV4_TCP_DEST_PORT_OFFSET     = IPV4_TCP_HEADER_OFFSET + 2;
1031     private static final int IPV4_TCP_SEQ_NUM_OFFSET       = IPV4_TCP_HEADER_OFFSET + 4;
1032     private static final int IPV4_TCP_ACK_NUM_OFFSET       = IPV4_TCP_HEADER_OFFSET + 8;
1033     private static final int IPV4_TCP_HEADER_LENGTH_OFFSET = IPV4_TCP_HEADER_OFFSET + 12;
1034     private static final int IPV4_TCP_HEADER_FLAG_OFFSET   = IPV4_TCP_HEADER_OFFSET + 13;
1035 
1036     private static final int IPV4_UDP_HEADER_OFFSET    = IP_HEADER_OFFSET + IPV4_HEADER_LEN;
1037     private static final int IPV4_UDP_SRC_PORT_OFFSET  = IPV4_UDP_HEADER_OFFSET + 0;
1038     private static final int IPV4_UDP_DEST_PORT_OFFSET = IPV4_UDP_HEADER_OFFSET + 2;
1039     private static final int IPV4_UDP_LENGTH_OFFSET    = IPV4_UDP_HEADER_OFFSET + 4;
1040     private static final int IPV4_UDP_PAYLOAD_OFFSET   = IPV4_UDP_HEADER_OFFSET + 8;
1041     private static final byte[] IPV4_BROADCAST_ADDRESS =
1042             {(byte) 255, (byte) 255, (byte) 255, (byte) 255};
1043 
1044     private static final int IPV6_HEADER_LEN             = 40;
1045     private static final int IPV6_PAYLOAD_LENGTH_OFFSET  = IP_HEADER_OFFSET + 4;
1046     private static final int IPV6_NEXT_HEADER_OFFSET     = IP_HEADER_OFFSET + 6;
1047     private static final int IPV6_SRC_ADDR_OFFSET        = IP_HEADER_OFFSET + 8;
1048     private static final int IPV6_DEST_ADDR_OFFSET       = IP_HEADER_OFFSET + 24;
1049     private static final int IPV6_TCP_HEADER_OFFSET      = IP_HEADER_OFFSET + IPV6_HEADER_LEN;
1050     private static final int IPV6_TCP_SRC_PORT_OFFSET    = IPV6_TCP_HEADER_OFFSET + 0;
1051     private static final int IPV6_TCP_DEST_PORT_OFFSET   = IPV6_TCP_HEADER_OFFSET + 2;
1052     private static final int IPV6_TCP_SEQ_NUM_OFFSET     = IPV6_TCP_HEADER_OFFSET + 4;
1053     private static final int IPV6_TCP_ACK_NUM_OFFSET     = IPV6_TCP_HEADER_OFFSET + 8;
1054     // The IPv6 all nodes address ff02::1
1055     private static final byte[] IPV6_ALL_NODES_ADDRESS   =
1056             { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
1057     private static final byte[] IPV6_ALL_ROUTERS_ADDRESS =
1058             { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 };
1059     private static final byte[] IPV6_SOLICITED_NODE_MULTICAST_ADDRESS = {
1060             (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1061             (byte) 0xff, (byte) 0xab, (byte) 0xcd, (byte) 0xef,
1062     };
1063 
1064     private static final int ICMP6_TYPE_OFFSET           = IP_HEADER_OFFSET + IPV6_HEADER_LEN;
1065     private static final int ICMP6_ROUTER_SOLICITATION   = 133;
1066     private static final int ICMP6_ROUTER_ADVERTISEMENT  = 134;
1067     private static final int ICMP6_NEIGHBOR_SOLICITATION = 135;
1068     private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136;
1069 
1070     private static final int ICMP6_RA_HEADER_LEN = 16;
1071     private static final int ICMP6_RA_CHECKSUM_OFFSET =
1072             IP_HEADER_OFFSET + IPV6_HEADER_LEN + 2;
1073     private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET =
1074             IP_HEADER_OFFSET + IPV6_HEADER_LEN + 6;
1075     private static final int ICMP6_RA_REACHABLE_TIME_OFFSET =
1076             IP_HEADER_OFFSET + IPV6_HEADER_LEN + 8;
1077     private static final int ICMP6_RA_RETRANSMISSION_TIMER_OFFSET =
1078             IP_HEADER_OFFSET + IPV6_HEADER_LEN + 12;
1079     private static final int ICMP6_RA_OPTION_OFFSET =
1080             IP_HEADER_OFFSET + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN;
1081 
1082     private static final int ICMP6_PREFIX_OPTION_TYPE                      = 3;
1083     private static final int ICMP6_PREFIX_OPTION_LEN                       = 32;
1084     private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET     = 4;
1085     private static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET = 8;
1086 
1087     // From RFC6106: Recursive DNS Server option
1088     private static final int ICMP6_RDNSS_OPTION_TYPE = 25;
1089     // From RFC6106: DNS Search List option
1090     private static final int ICMP6_DNSSL_OPTION_TYPE = 31;
1091 
1092     // From RFC4191: Route Information option
1093     private static final int ICMP6_ROUTE_INFO_OPTION_TYPE = 24;
1094     // Above three options all have the same format:
1095     private static final int ICMP6_4_BYTE_OPTION_LEN      = 8;
1096     private static final int ICMP6_4_BYTE_LIFETIME_OFFSET = 4;
1097     private static final int ICMP6_4_BYTE_LIFETIME_LEN    = 4;
1098 
1099     private static final int UDP_HEADER_LEN              = 8;
1100     private static final int UDP_DESTINATION_PORT_OFFSET = ETH_HEADER_LEN + 22;
1101 
1102     private static final int DHCP_CLIENT_PORT       = 68;
1103     private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 48;
1104 
1105     private static final int ARP_HEADER_OFFSET          = ETH_HEADER_LEN;
1106     private static final byte[] ARP_IPV4_REQUEST_HEADER = {
1107             0, 1, // Hardware type: Ethernet (1)
1108             8, 0, // Protocol type: IP (0x0800)
1109             6,    // Hardware size: 6
1110             4,    // Protocol size: 4
1111             0, 1  // Opcode: request (1)
1112     };
1113     private static final byte[] ARP_IPV4_REPLY_HEADER = {
1114             0, 1, // Hardware type: Ethernet (1)
1115             8, 0, // Protocol type: IP (0x0800)
1116             6,    // Hardware size: 6
1117             4,    // Protocol size: 4
1118             0, 2  // Opcode: reply (2)
1119     };
1120     private static final int ARP_SOURCE_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 14;
1121     private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 24;
1122 
1123     private static final byte[] MOCK_IPV4_ADDR           = {10, 0, 0, 1};
1124     private static final byte[] MOCK_BROADCAST_IPV4_ADDR = {10, 0, 31, (byte) 255}; // prefix = 19
1125     private static final byte[] MOCK_MULTICAST_IPV4_ADDR = {(byte) 224, 0, 0, 1};
1126     private static final byte[] ANOTHER_IPV4_ADDR        = {10, 0, 0, 2};
1127     private static final byte[] IPV4_SOURCE_ADDR         = {10, 0, 0, 3};
1128     private static final byte[] ANOTHER_IPV4_SOURCE_ADDR = {(byte) 192, 0, 2, 1};
1129     private static final byte[] BUG_PROBE_SOURCE_ADDR1   = {0, 0, 1, 2};
1130     private static final byte[] BUG_PROBE_SOURCE_ADDR2   = {3, 4, 0, 0};
1131     private static final byte[] IPV4_ANY_HOST_ADDR       = {0, 0, 0, 0};
1132 
1133     // Helper to initialize a default apfFilter.
setupApfFilter( IpClientCallbacksWrapper ipClientCallback, ApfConfiguration config)1134     private ApfFilter setupApfFilter(
1135             IpClientCallbacksWrapper ipClientCallback, ApfConfiguration config) throws Exception {
1136         LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
1137         LinkProperties lp = new LinkProperties();
1138         lp.addLinkAddress(link);
1139         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
1140         apfFilter.setLinkProperties(lp);
1141         return apfFilter;
1142     }
1143 
setIpv4VersionFields(ByteBuffer packet)1144     private static void setIpv4VersionFields(ByteBuffer packet) {
1145         packet.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IP);
1146         packet.put(IP_HEADER_OFFSET, (byte) 0x45);
1147     }
1148 
setIpv6VersionFields(ByteBuffer packet)1149     private static void setIpv6VersionFields(ByteBuffer packet) {
1150         packet.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IPV6);
1151         packet.put(IP_HEADER_OFFSET, (byte) 0x60);
1152     }
1153 
makeIpv4Packet(int proto)1154     private static ByteBuffer makeIpv4Packet(int proto) {
1155         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1156         setIpv4VersionFields(packet);
1157         packet.put(IPV4_PROTOCOL_OFFSET, (byte) proto);
1158         return packet;
1159     }
1160 
makeIpv6Packet(int nextHeader)1161     private static ByteBuffer makeIpv6Packet(int nextHeader) {
1162         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1163         setIpv6VersionFields(packet);
1164         packet.put(IPV6_NEXT_HEADER_OFFSET, (byte) nextHeader);
1165         return packet;
1166     }
1167 
1168     @Test
testApfFilterIPv4()1169     public void testApfFilterIPv4() throws Exception {
1170         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
1171         LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
1172         LinkProperties lp = new LinkProperties();
1173         lp.addLinkAddress(link);
1174 
1175         ApfConfiguration config = getDefaultConfig();
1176         config.multicastFilter = DROP_MULTICAST;
1177         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
1178         apfFilter.setLinkProperties(lp);
1179 
1180         byte[] program = ipClientCallback.getApfProgram();
1181 
1182         // Verify empty packet of 100 zero bytes is passed
1183         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1184         assertPass(program, packet.array());
1185 
1186         // Verify unicast IPv4 packet is passed
1187         put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
1188         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1189         put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_IPV4_ADDR);
1190         assertPass(program, packet.array());
1191 
1192         // Verify L2 unicast to IPv4 broadcast addresses is dropped (b/30231088)
1193         put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
1194         assertDrop(program, packet.array());
1195         put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR);
1196         assertDrop(program, packet.array());
1197 
1198         // Verify multicast/broadcast IPv4, not DHCP to us, is dropped
1199         put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
1200         assertDrop(program, packet.array());
1201         packet.put(IP_HEADER_OFFSET, (byte) 0x45);
1202         assertDrop(program, packet.array());
1203         packet.put(IPV4_PROTOCOL_OFFSET, (byte)IPPROTO_UDP);
1204         assertDrop(program, packet.array());
1205         packet.putShort(UDP_DESTINATION_PORT_OFFSET, (short)DHCP_CLIENT_PORT);
1206         assertDrop(program, packet.array());
1207         put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_MULTICAST_IPV4_ADDR);
1208         assertDrop(program, packet.array());
1209         put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR);
1210         assertDrop(program, packet.array());
1211         put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
1212         assertDrop(program, packet.array());
1213 
1214         // Verify broadcast IPv4 DHCP to us is passed
1215         put(packet, DHCP_CLIENT_MAC_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
1216         assertPass(program, packet.array());
1217 
1218         // Verify unicast IPv4 DHCP to us is passed
1219         put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
1220         assertPass(program, packet.array());
1221 
1222         apfFilter.shutdown();
1223     }
1224 
1225     @Test
testApfFilterIPv6()1226     public void testApfFilterIPv6() throws Exception {
1227         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
1228         ApfConfiguration config = getDefaultConfig();
1229         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
1230         byte[] program = ipClientCallback.getApfProgram();
1231 
1232         // Verify empty IPv6 packet is passed
1233         ByteBuffer packet = makeIpv6Packet(IPPROTO_UDP);
1234         assertPass(program, packet.array());
1235 
1236         // Verify empty ICMPv6 packet is passed
1237         packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
1238         assertPass(program, packet.array());
1239 
1240         // Verify empty ICMPv6 NA packet is passed
1241         packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_NEIGHBOR_ANNOUNCEMENT);
1242         assertPass(program, packet.array());
1243 
1244         // Verify ICMPv6 NA to ff02::1 is dropped
1245         put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_NODES_ADDRESS);
1246         assertDrop(program, packet.array());
1247 
1248         // Verify ICMPv6 NA to ff02::2 is dropped
1249         put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_ROUTERS_ADDRESS);
1250         assertDrop(program, packet.array());
1251 
1252         // Verify ICMPv6 NA to Solicited-Node Multicast is passed
1253         put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_SOLICITED_NODE_MULTICAST_ADDRESS);
1254         assertPass(program, packet.array());
1255 
1256         // Verify ICMPv6 RS to any is dropped
1257         packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_SOLICITATION);
1258         assertDrop(program, packet.array());
1259         put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_ROUTERS_ADDRESS);
1260         assertDrop(program, packet.array());
1261 
1262         apfFilter.shutdown();
1263     }
1264 
1265     @Test
testApfFilterMulticast()1266     public void testApfFilterMulticast() throws Exception {
1267         final byte[] unicastIpv4Addr   = {(byte)192,0,2,63};
1268         final byte[] broadcastIpv4Addr = {(byte)192,0,2,(byte)255};
1269         final byte[] multicastIpv4Addr = {(byte)224,0,0,1};
1270         final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb};
1271 
1272         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
1273         LinkAddress link = new LinkAddress(InetAddress.getByAddress(unicastIpv4Addr), 24);
1274         LinkProperties lp = new LinkProperties();
1275         lp.addLinkAddress(link);
1276 
1277         ApfConfiguration config = getDefaultConfig();
1278         config.ieee802_3Filter = DROP_802_3_FRAMES;
1279         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
1280         apfFilter.setLinkProperties(lp);
1281 
1282         byte[] program = ipClientCallback.getApfProgram();
1283 
1284         // Construct IPv4 and IPv6 multicast packets.
1285         ByteBuffer mcastv4packet = makeIpv4Packet(IPPROTO_UDP);
1286         put(mcastv4packet, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr);
1287 
1288         ByteBuffer mcastv6packet = makeIpv6Packet(IPPROTO_UDP);
1289         put(mcastv6packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr);
1290 
1291         // Construct IPv4 broadcast packet.
1292         ByteBuffer bcastv4packet1 = makeIpv4Packet(IPPROTO_UDP);
1293         bcastv4packet1.put(ETH_BROADCAST_MAC_ADDRESS);
1294         bcastv4packet1.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1295         put(bcastv4packet1, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr);
1296 
1297         ByteBuffer bcastv4packet2 = makeIpv4Packet(IPPROTO_UDP);
1298         bcastv4packet2.put(ETH_BROADCAST_MAC_ADDRESS);
1299         bcastv4packet2.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1300         put(bcastv4packet2, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
1301 
1302         // Construct IPv4 broadcast with L2 unicast address packet (b/30231088).
1303         ByteBuffer bcastv4unicastl2packet = makeIpv4Packet(IPPROTO_UDP);
1304         bcastv4unicastl2packet.put(TestApfFilter.MOCK_MAC_ADDR);
1305         bcastv4unicastl2packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1306         put(bcastv4unicastl2packet, IPV4_DEST_ADDR_OFFSET, broadcastIpv4Addr);
1307 
1308         // Verify initially disabled multicast filter is off
1309         assertPass(program, mcastv4packet.array());
1310         assertPass(program, mcastv6packet.array());
1311         assertPass(program, bcastv4packet1.array());
1312         assertPass(program, bcastv4packet2.array());
1313         assertPass(program, bcastv4unicastl2packet.array());
1314 
1315         // Turn on multicast filter and verify it works
1316         ipClientCallback.resetApfProgramWait();
1317         apfFilter.setMulticastFilter(true);
1318         program = ipClientCallback.getApfProgram();
1319         assertDrop(program, mcastv4packet.array());
1320         assertDrop(program, mcastv6packet.array());
1321         assertDrop(program, bcastv4packet1.array());
1322         assertDrop(program, bcastv4packet2.array());
1323         assertDrop(program, bcastv4unicastl2packet.array());
1324 
1325         // Turn off multicast filter and verify it's off
1326         ipClientCallback.resetApfProgramWait();
1327         apfFilter.setMulticastFilter(false);
1328         program = ipClientCallback.getApfProgram();
1329         assertPass(program, mcastv4packet.array());
1330         assertPass(program, mcastv6packet.array());
1331         assertPass(program, bcastv4packet1.array());
1332         assertPass(program, bcastv4packet2.array());
1333         assertPass(program, bcastv4unicastl2packet.array());
1334 
1335         // Verify it can be initialized to on
1336         ipClientCallback.resetApfProgramWait();
1337         apfFilter.shutdown();
1338         config.multicastFilter = DROP_MULTICAST;
1339         config.ieee802_3Filter = DROP_802_3_FRAMES;
1340         apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
1341         apfFilter.setLinkProperties(lp);
1342         program = ipClientCallback.getApfProgram();
1343         assertDrop(program, mcastv4packet.array());
1344         assertDrop(program, mcastv6packet.array());
1345         assertDrop(program, bcastv4packet1.array());
1346         assertDrop(program, bcastv4unicastl2packet.array());
1347 
1348         // Verify that ICMPv6 multicast is not dropped.
1349         mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
1350         assertPass(program, mcastv6packet.array());
1351 
1352         apfFilter.shutdown();
1353     }
1354 
1355     @Test
testApfFilterMulticastPingWhileDozing()1356     public void testApfFilterMulticastPingWhileDozing() throws Exception {
1357         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
1358         ApfFilter apfFilter = setupApfFilter(ipClientCallback, getDefaultConfig());
1359 
1360         // Construct a multicast ICMPv6 ECHO request.
1361         final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb};
1362         ByteBuffer packet = makeIpv6Packet(IPPROTO_ICMPV6);
1363         packet.put(ICMP6_TYPE_OFFSET, (byte)ICMPV6_ECHO_REQUEST_TYPE);
1364         put(packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr);
1365 
1366         // Normally, we let multicast pings alone...
1367         assertPass(ipClientCallback.getApfProgram(), packet.array());
1368 
1369         // ...and even while dozing...
1370         apfFilter.setDozeMode(true);
1371         assertPass(ipClientCallback.getApfProgram(), packet.array());
1372 
1373         // ...but when the multicast filter is also enabled, drop the multicast pings to save power.
1374         apfFilter.setMulticastFilter(true);
1375         assertDrop(ipClientCallback.getApfProgram(), packet.array());
1376 
1377         // However, we should still let through all other ICMPv6 types.
1378         ByteBuffer raPacket = ByteBuffer.wrap(packet.array().clone());
1379         setIpv6VersionFields(packet);
1380         packet.put(IPV6_NEXT_HEADER_OFFSET, (byte) IPPROTO_ICMPV6);
1381         raPacket.put(ICMP6_TYPE_OFFSET, (byte) NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT);
1382         assertPass(ipClientCallback.getApfProgram(), raPacket.array());
1383 
1384         // Now wake up from doze mode to ensure that we no longer drop the packets.
1385         // (The multicast filter is still enabled at this point).
1386         apfFilter.setDozeMode(false);
1387         assertPass(ipClientCallback.getApfProgram(), packet.array());
1388 
1389         apfFilter.shutdown();
1390     }
1391 
1392     @Test
testApfFilter802_3()1393     public void testApfFilter802_3() throws Exception {
1394         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
1395         ApfConfiguration config = getDefaultConfig();
1396         ApfFilter apfFilter = setupApfFilter(ipClientCallback, config);
1397         byte[] program = ipClientCallback.getApfProgram();
1398 
1399         // Verify empty packet of 100 zero bytes is passed
1400         // Note that eth-type = 0 makes it an IEEE802.3 frame
1401         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1402         assertPass(program, packet.array());
1403 
1404         // Verify empty packet with IPv4 is passed
1405         setIpv4VersionFields(packet);
1406         assertPass(program, packet.array());
1407 
1408         // Verify empty IPv6 packet is passed
1409         setIpv6VersionFields(packet);
1410         assertPass(program, packet.array());
1411 
1412         // Now turn on the filter
1413         ipClientCallback.resetApfProgramWait();
1414         apfFilter.shutdown();
1415         config.ieee802_3Filter = DROP_802_3_FRAMES;
1416         apfFilter = setupApfFilter(ipClientCallback, config);
1417         program = ipClientCallback.getApfProgram();
1418 
1419         // Verify that IEEE802.3 frame is dropped
1420         // In this case ethtype is used for payload length
1421         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)(100 - 14));
1422         assertDrop(program, packet.array());
1423 
1424         // Verify that IPv4 (as example of Ethernet II) frame will pass
1425         setIpv4VersionFields(packet);
1426         assertPass(program, packet.array());
1427 
1428         // Verify that IPv6 (as example of Ethernet II) frame will pass
1429         setIpv6VersionFields(packet);
1430         assertPass(program, packet.array());
1431 
1432         apfFilter.shutdown();
1433     }
1434 
1435     @Test
testApfFilterEthTypeBL()1436     public void testApfFilterEthTypeBL() throws Exception {
1437         final int[] emptyBlackList = {};
1438         final int[] ipv4BlackList = {ETH_P_IP};
1439         final int[] ipv4Ipv6BlackList = {ETH_P_IP, ETH_P_IPV6};
1440 
1441         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
1442         ApfConfiguration config = getDefaultConfig();
1443         ApfFilter apfFilter = setupApfFilter(ipClientCallback, config);
1444         byte[] program = ipClientCallback.getApfProgram();
1445 
1446         // Verify empty packet of 100 zero bytes is passed
1447         // Note that eth-type = 0 makes it an IEEE802.3 frame
1448         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1449         assertPass(program, packet.array());
1450 
1451         // Verify empty packet with IPv4 is passed
1452         setIpv4VersionFields(packet);
1453         assertPass(program, packet.array());
1454 
1455         // Verify empty IPv6 packet is passed
1456         setIpv6VersionFields(packet);
1457         assertPass(program, packet.array());
1458 
1459         // Now add IPv4 to the black list
1460         ipClientCallback.resetApfProgramWait();
1461         apfFilter.shutdown();
1462         config.ethTypeBlackList = ipv4BlackList;
1463         apfFilter = setupApfFilter(ipClientCallback, config);
1464         program = ipClientCallback.getApfProgram();
1465 
1466         // Verify that IPv4 frame will be dropped
1467         setIpv4VersionFields(packet);
1468         assertDrop(program, packet.array());
1469 
1470         // Verify that IPv6 frame will pass
1471         setIpv6VersionFields(packet);
1472         assertPass(program, packet.array());
1473 
1474         // Now let us have both IPv4 and IPv6 in the black list
1475         ipClientCallback.resetApfProgramWait();
1476         apfFilter.shutdown();
1477         config.ethTypeBlackList = ipv4Ipv6BlackList;
1478         apfFilter = setupApfFilter(ipClientCallback, config);
1479         program = ipClientCallback.getApfProgram();
1480 
1481         // Verify that IPv4 frame will be dropped
1482         setIpv4VersionFields(packet);
1483         assertDrop(program, packet.array());
1484 
1485         // Verify that IPv6 frame will be dropped
1486         setIpv6VersionFields(packet);
1487         assertDrop(program, packet.array());
1488 
1489         apfFilter.shutdown();
1490     }
1491 
getProgram(MockIpClientCallback cb, ApfFilter filter, LinkProperties lp)1492     private byte[] getProgram(MockIpClientCallback cb, ApfFilter filter, LinkProperties lp) {
1493         cb.resetApfProgramWait();
1494         filter.setLinkProperties(lp);
1495         return cb.getApfProgram();
1496     }
1497 
verifyArpFilter(byte[] program, int filterResult)1498     private void verifyArpFilter(byte[] program, int filterResult) {
1499         // Verify ARP request packet
1500         assertPass(program, arpRequestBroadcast(MOCK_IPV4_ADDR));
1501         assertVerdict(filterResult, program, arpRequestBroadcast(ANOTHER_IPV4_ADDR));
1502         assertDrop(program, arpRequestBroadcast(IPV4_ANY_HOST_ADDR));
1503 
1504         // Verify ARP reply packets from different source ip
1505         assertDrop(program, arpReply(IPV4_ANY_HOST_ADDR, IPV4_ANY_HOST_ADDR));
1506         assertPass(program, arpReply(ANOTHER_IPV4_SOURCE_ADDR, IPV4_ANY_HOST_ADDR));
1507         assertPass(program, arpReply(BUG_PROBE_SOURCE_ADDR1, IPV4_ANY_HOST_ADDR));
1508         assertPass(program, arpReply(BUG_PROBE_SOURCE_ADDR2, IPV4_ANY_HOST_ADDR));
1509 
1510         // Verify unicast ARP reply packet is always accepted.
1511         assertPass(program, arpReply(IPV4_SOURCE_ADDR, MOCK_IPV4_ADDR));
1512         assertPass(program, arpReply(IPV4_SOURCE_ADDR, ANOTHER_IPV4_ADDR));
1513         assertPass(program, arpReply(IPV4_SOURCE_ADDR, IPV4_ANY_HOST_ADDR));
1514 
1515         // Verify GARP reply packets are always filtered
1516         assertDrop(program, garpReply());
1517     }
1518 
1519     @Test
testApfFilterArp()1520     public void testApfFilterArp() throws Exception {
1521         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
1522         ApfConfiguration config = getDefaultConfig();
1523         config.multicastFilter = DROP_MULTICAST;
1524         config.ieee802_3Filter = DROP_802_3_FRAMES;
1525         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
1526 
1527         // Verify initially ARP request filter is off, and GARP filter is on.
1528         verifyArpFilter(ipClientCallback.getApfProgram(), PASS);
1529 
1530         // Inform ApfFilter of our address and verify ARP filtering is on
1531         LinkAddress linkAddress = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 24);
1532         LinkProperties lp = new LinkProperties();
1533         assertTrue(lp.addLinkAddress(linkAddress));
1534         verifyArpFilter(getProgram(ipClientCallback, apfFilter, lp), DROP);
1535 
1536         // Inform ApfFilter of loss of IP and verify ARP filtering is off
1537         verifyArpFilter(getProgram(ipClientCallback, apfFilter, new LinkProperties()), PASS);
1538 
1539         apfFilter.shutdown();
1540     }
1541 
arpReply(byte[] sip, byte[] tip)1542     private static byte[] arpReply(byte[] sip, byte[] tip) {
1543         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1544         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
1545         put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
1546         put(packet, ARP_SOURCE_IP_ADDRESS_OFFSET, sip);
1547         put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip);
1548         return packet.array();
1549     }
1550 
arpRequestBroadcast(byte[] tip)1551     private static byte[] arpRequestBroadcast(byte[] tip) {
1552         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1553         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
1554         put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
1555         put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REQUEST_HEADER);
1556         put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip);
1557         return packet.array();
1558     }
1559 
garpReply()1560     private static byte[] garpReply() {
1561         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1562         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
1563         put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
1564         put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
1565         put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, IPV4_ANY_HOST_ADDR);
1566         return packet.array();
1567     }
1568 
1569     private static final byte[] IPV4_KEEPALIVE_SRC_ADDR = {10, 0, 0, 5};
1570     private static final byte[] IPV4_KEEPALIVE_DST_ADDR = {10, 0, 0, 6};
1571     private static final byte[] IPV4_ANOTHER_ADDR = {10, 0 , 0, 7};
1572     private static final byte[] IPV6_KEEPALIVE_SRC_ADDR =
1573             {(byte) 0x24, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xfa, (byte) 0xf1};
1574     private static final byte[] IPV6_KEEPALIVE_DST_ADDR =
1575             {(byte) 0x24, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xfa, (byte) 0xf2};
1576     private static final byte[] IPV6_ANOTHER_ADDR =
1577             {(byte) 0x24, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xfa, (byte) 0xf5};
1578 
1579     @Test
testApfFilterKeepaliveAck()1580     public void testApfFilterKeepaliveAck() throws Exception {
1581         final MockIpClientCallback cb = new MockIpClientCallback();
1582         final ApfConfiguration config = getDefaultConfig();
1583         config.multicastFilter = DROP_MULTICAST;
1584         config.ieee802_3Filter = DROP_802_3_FRAMES;
1585         final TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog);
1586         byte[] program;
1587         final int srcPort = 12345;
1588         final int dstPort = 54321;
1589         final int seqNum = 2123456789;
1590         final int ackNum = 1234567890;
1591         final int anotherSrcPort = 23456;
1592         final int anotherDstPort = 65432;
1593         final int anotherSeqNum = 2123456780;
1594         final int anotherAckNum = 1123456789;
1595         final int slot1 = 1;
1596         final int slot2 = 2;
1597         final int window = 14480;
1598         final int windowScale = 4;
1599 
1600         // src: 10.0.0.5, port: 12345
1601         // dst: 10.0.0.6, port: 54321
1602         InetAddress srcAddr = InetAddress.getByAddress(IPV4_KEEPALIVE_SRC_ADDR);
1603         InetAddress dstAddr = InetAddress.getByAddress(IPV4_KEEPALIVE_DST_ADDR);
1604 
1605         final TcpKeepalivePacketDataParcelable parcel = new TcpKeepalivePacketDataParcelable();
1606         parcel.srcAddress = srcAddr.getAddress();
1607         parcel.srcPort = srcPort;
1608         parcel.dstAddress = dstAddr.getAddress();
1609         parcel.dstPort = dstPort;
1610         parcel.seq = seqNum;
1611         parcel.ack = ackNum;
1612 
1613         apfFilter.addTcpKeepalivePacketFilter(slot1, parcel);
1614         program = cb.getApfProgram();
1615 
1616         // Verify IPv4 keepalive ack packet is dropped
1617         // src: 10.0.0.6, port: 54321
1618         // dst: 10.0.0.5, port: 12345
1619         assertDrop(program,
1620                 ipv4TcpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
1621                         dstPort, srcPort, ackNum, seqNum + 1, 0 /* dataLength */));
1622         // Verify IPv4 non-keepalive ack packet from the same source address is passed
1623         assertPass(program,
1624                 ipv4TcpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
1625                         dstPort, srcPort, ackNum + 100, seqNum, 0 /* dataLength */));
1626         assertPass(program,
1627                 ipv4TcpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
1628                         dstPort, srcPort, ackNum, seqNum + 1, 10 /* dataLength */));
1629         // Verify IPv4 packet from another address is passed
1630         assertPass(program,
1631                 ipv4TcpPacket(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR, anotherSrcPort,
1632                         anotherDstPort, anotherSeqNum, anotherAckNum, 0 /* dataLength */));
1633 
1634         // Remove IPv4 keepalive filter
1635         apfFilter.removeKeepalivePacketFilter(slot1);
1636 
1637         try {
1638             // src: 2404:0:0:0:0:0:faf1, port: 12345
1639             // dst: 2404:0:0:0:0:0:faf2, port: 54321
1640             srcAddr = InetAddress.getByAddress(IPV6_KEEPALIVE_SRC_ADDR);
1641             dstAddr = InetAddress.getByAddress(IPV6_KEEPALIVE_DST_ADDR);
1642 
1643             final TcpKeepalivePacketDataParcelable ipv6Parcel =
1644                     new TcpKeepalivePacketDataParcelable();
1645             ipv6Parcel.srcAddress = srcAddr.getAddress();
1646             ipv6Parcel.srcPort = srcPort;
1647             ipv6Parcel.dstAddress = dstAddr.getAddress();
1648             ipv6Parcel.dstPort = dstPort;
1649             ipv6Parcel.seq = seqNum;
1650             ipv6Parcel.ack = ackNum;
1651 
1652             apfFilter.addTcpKeepalivePacketFilter(slot1, ipv6Parcel);
1653             program = cb.getApfProgram();
1654 
1655             // Verify IPv6 keepalive ack packet is dropped
1656             // src: 2404:0:0:0:0:0:faf2, port: 54321
1657             // dst: 2404:0:0:0:0:0:faf1, port: 12345
1658             assertDrop(program,
1659                     ipv6TcpPacket(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR,
1660                             dstPort, srcPort, ackNum, seqNum + 1));
1661             // Verify IPv6 non-keepalive ack packet from the same source address is passed
1662             assertPass(program,
1663                     ipv6TcpPacket(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR,
1664                             dstPort, srcPort, ackNum + 100, seqNum));
1665             // Verify IPv6 packet from another address is passed
1666             assertPass(program,
1667                     ipv6TcpPacket(IPV6_ANOTHER_ADDR, IPV6_KEEPALIVE_SRC_ADDR, anotherSrcPort,
1668                             anotherDstPort, anotherSeqNum, anotherAckNum));
1669 
1670             // Remove IPv6 keepalive filter
1671             apfFilter.removeKeepalivePacketFilter(slot1);
1672 
1673             // Verify multiple filters
1674             apfFilter.addTcpKeepalivePacketFilter(slot1, parcel);
1675             apfFilter.addTcpKeepalivePacketFilter(slot2, ipv6Parcel);
1676             program = cb.getApfProgram();
1677 
1678             // Verify IPv4 keepalive ack packet is dropped
1679             // src: 10.0.0.6, port: 54321
1680             // dst: 10.0.0.5, port: 12345
1681             assertDrop(program,
1682                     ipv4TcpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
1683                             dstPort, srcPort, ackNum, seqNum + 1, 0 /* dataLength */));
1684             // Verify IPv4 non-keepalive ack packet from the same source address is passed
1685             assertPass(program,
1686                     ipv4TcpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
1687                             dstPort, srcPort, ackNum + 100, seqNum, 0 /* dataLength */));
1688             // Verify IPv4 packet from another address is passed
1689             assertPass(program,
1690                     ipv4TcpPacket(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR, anotherSrcPort,
1691                             anotherDstPort, anotherSeqNum, anotherAckNum, 0 /* dataLength */));
1692 
1693             // Verify IPv6 keepalive ack packet is dropped
1694             // src: 2404:0:0:0:0:0:faf2, port: 54321
1695             // dst: 2404:0:0:0:0:0:faf1, port: 12345
1696             assertDrop(program,
1697                     ipv6TcpPacket(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR,
1698                             dstPort, srcPort, ackNum, seqNum + 1));
1699             // Verify IPv6 non-keepalive ack packet from the same source address is passed
1700             assertPass(program,
1701                     ipv6TcpPacket(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR,
1702                             dstPort, srcPort, ackNum + 100, seqNum));
1703             // Verify IPv6 packet from another address is passed
1704             assertPass(program,
1705                     ipv6TcpPacket(IPV6_ANOTHER_ADDR, IPV6_KEEPALIVE_SRC_ADDR, anotherSrcPort,
1706                             anotherDstPort, anotherSeqNum, anotherAckNum));
1707 
1708             // Remove keepalive filters
1709             apfFilter.removeKeepalivePacketFilter(slot1);
1710             apfFilter.removeKeepalivePacketFilter(slot2);
1711         } catch (UnsupportedOperationException e) {
1712             // TODO: support V6 packets
1713         }
1714 
1715         program = cb.getApfProgram();
1716 
1717         // Verify IPv4, IPv6 packets are passed
1718         assertPass(program,
1719                 ipv4TcpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
1720                         dstPort, srcPort, ackNum, seqNum + 1, 0 /* dataLength */));
1721         assertPass(program,
1722                 ipv6TcpPacket(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR,
1723                         dstPort, srcPort, ackNum, seqNum + 1));
1724         assertPass(program,
1725                 ipv4TcpPacket(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR, srcPort,
1726                         dstPort, anotherSeqNum, anotherAckNum, 0 /* dataLength */));
1727         assertPass(program,
1728                 ipv6TcpPacket(IPV6_ANOTHER_ADDR, IPV6_KEEPALIVE_SRC_ADDR, srcPort,
1729                         dstPort, anotherSeqNum, anotherAckNum));
1730 
1731         apfFilter.shutdown();
1732     }
1733 
ipv4TcpPacket(byte[] sip, byte[] dip, int sport, int dport, int seq, int ack, int dataLength)1734     private static byte[] ipv4TcpPacket(byte[] sip, byte[] dip, int sport,
1735             int dport, int seq, int ack, int dataLength) {
1736         final int totalLength = dataLength + IPV4_HEADER_LEN + IPV4_TCP_HEADER_LEN;
1737 
1738         ByteBuffer packet = ByteBuffer.wrap(new byte[totalLength + ETH_HEADER_LEN]);
1739 
1740         // Ethertype and IPv4 header
1741         setIpv4VersionFields(packet);
1742         packet.putShort(IPV4_TOTAL_LENGTH_OFFSET, (short) totalLength);
1743         packet.put(IPV4_PROTOCOL_OFFSET, (byte) IPPROTO_TCP);
1744         put(packet, IPV4_SRC_ADDR_OFFSET, sip);
1745         put(packet, IPV4_DEST_ADDR_OFFSET, dip);
1746         packet.putShort(IPV4_TCP_SRC_PORT_OFFSET, (short) sport);
1747         packet.putShort(IPV4_TCP_DEST_PORT_OFFSET, (short) dport);
1748         packet.putInt(IPV4_TCP_SEQ_NUM_OFFSET, seq);
1749         packet.putInt(IPV4_TCP_ACK_NUM_OFFSET, ack);
1750 
1751         // TCP header length 5(20 bytes), reserved 3 bits, NS=0
1752         packet.put(IPV4_TCP_HEADER_LENGTH_OFFSET, (byte) 0x50);
1753         // TCP flags: ACK set
1754         packet.put(IPV4_TCP_HEADER_FLAG_OFFSET, (byte) 0x10);
1755         return packet.array();
1756     }
1757 
ipv6TcpPacket(byte[] sip, byte[] tip, int sport, int dport, int seq, int ack)1758     private static byte[] ipv6TcpPacket(byte[] sip, byte[] tip, int sport,
1759             int dport, int seq, int ack) {
1760         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1761         setIpv6VersionFields(packet);
1762         packet.put(IPV6_NEXT_HEADER_OFFSET, (byte) IPPROTO_TCP);
1763         put(packet, IPV6_SRC_ADDR_OFFSET, sip);
1764         put(packet, IPV6_DEST_ADDR_OFFSET, tip);
1765         packet.putShort(IPV6_TCP_SRC_PORT_OFFSET, (short) sport);
1766         packet.putShort(IPV6_TCP_DEST_PORT_OFFSET, (short) dport);
1767         packet.putInt(IPV6_TCP_SEQ_NUM_OFFSET, seq);
1768         packet.putInt(IPV6_TCP_ACK_NUM_OFFSET, ack);
1769         return packet.array();
1770     }
1771 
1772     @Test
testApfFilterNattKeepalivePacket()1773     public void testApfFilterNattKeepalivePacket() throws Exception {
1774         final MockIpClientCallback cb = new MockIpClientCallback();
1775         final ApfConfiguration config = getDefaultConfig();
1776         config.multicastFilter = DROP_MULTICAST;
1777         config.ieee802_3Filter = DROP_802_3_FRAMES;
1778         final TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog);
1779         byte[] program;
1780         final int srcPort = 1024;
1781         final int dstPort = 4500;
1782         final int slot1 = 1;
1783         // NAT-T keepalive
1784         final byte[] kaPayload = {(byte) 0xff};
1785         final byte[] nonKaPayload = {(byte) 0xfe};
1786 
1787         // src: 10.0.0.5, port: 1024
1788         // dst: 10.0.0.6, port: 4500
1789         InetAddress srcAddr = InetAddress.getByAddress(IPV4_KEEPALIVE_SRC_ADDR);
1790         InetAddress dstAddr = InetAddress.getByAddress(IPV4_KEEPALIVE_DST_ADDR);
1791 
1792         final NattKeepalivePacketDataParcelable parcel = new NattKeepalivePacketDataParcelable();
1793         parcel.srcAddress = srcAddr.getAddress();
1794         parcel.srcPort = srcPort;
1795         parcel.dstAddress = dstAddr.getAddress();
1796         parcel.dstPort = dstPort;
1797 
1798         apfFilter.addNattKeepalivePacketFilter(slot1, parcel);
1799         program = cb.getApfProgram();
1800 
1801         // Verify IPv4 keepalive packet is dropped
1802         // src: 10.0.0.6, port: 4500
1803         // dst: 10.0.0.5, port: 1024
1804         byte[] pkt = ipv4UdpPacket(IPV4_KEEPALIVE_DST_ADDR,
1805                     IPV4_KEEPALIVE_SRC_ADDR, dstPort, srcPort, 1 /* dataLength */);
1806         System.arraycopy(kaPayload, 0, pkt, IPV4_UDP_PAYLOAD_OFFSET, kaPayload.length);
1807         assertDrop(program, pkt);
1808 
1809         // Verify a packet with payload length 1 byte but it is not 0xff will pass the filter.
1810         System.arraycopy(nonKaPayload, 0, pkt, IPV4_UDP_PAYLOAD_OFFSET, nonKaPayload.length);
1811         assertPass(program, pkt);
1812 
1813         // Verify IPv4 non-keepalive response packet from the same source address is passed
1814         assertPass(program,
1815                 ipv4UdpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
1816                         dstPort, srcPort, 10 /* dataLength */));
1817 
1818         // Verify IPv4 non-keepalive response packet from other source address is passed
1819         assertPass(program,
1820                 ipv4UdpPacket(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
1821                         dstPort, srcPort, 10 /* dataLength */));
1822 
1823         apfFilter.removeKeepalivePacketFilter(slot1);
1824         apfFilter.shutdown();
1825     }
1826 
ipv4UdpPacket(byte[] sip, byte[] dip, int sport, int dport, int dataLength)1827     private static byte[] ipv4UdpPacket(byte[] sip, byte[] dip, int sport,
1828             int dport, int dataLength) {
1829         final int totalLength = dataLength + IPV4_HEADER_LEN + UDP_HEADER_LEN;
1830         final int udpLength = UDP_HEADER_LEN + dataLength;
1831         ByteBuffer packet = ByteBuffer.wrap(new byte[totalLength + ETH_HEADER_LEN]);
1832 
1833         // Ethertype and IPv4 header
1834         setIpv4VersionFields(packet);
1835         packet.putShort(IPV4_TOTAL_LENGTH_OFFSET, (short) totalLength);
1836         packet.put(IPV4_PROTOCOL_OFFSET, (byte) IPPROTO_UDP);
1837         put(packet, IPV4_SRC_ADDR_OFFSET, sip);
1838         put(packet, IPV4_DEST_ADDR_OFFSET, dip);
1839         packet.putShort(IPV4_UDP_SRC_PORT_OFFSET, (short) sport);
1840         packet.putShort(IPV4_UDP_DEST_PORT_OFFSET, (short) dport);
1841         packet.putShort(IPV4_UDP_LENGTH_OFFSET, (short) udpLength);
1842 
1843         return packet.array();
1844     }
1845 
addRdnssOption(ByteBuffer packet, int lifetime, String... servers)1846     private void addRdnssOption(ByteBuffer packet, int lifetime, String... servers)
1847             throws Exception {
1848         int optionLength = 1 + 2 * servers.length;   // In 8-byte units
1849         packet.put((byte) ICMP6_RDNSS_OPTION_TYPE);  // Type
1850         packet.put((byte) optionLength);             // Length
1851         packet.putShort((short) 0);                  // Reserved
1852         packet.putInt(lifetime);                     // Lifetime
1853         for (String server : servers) {
1854             packet.put(InetAddress.getByName(server).getAddress());
1855         }
1856     }
1857 
addRioOption(ByteBuffer packet, int lifetime, String prefixString)1858     private void addRioOption(ByteBuffer packet, int lifetime, String prefixString)
1859             throws Exception {
1860         IpPrefix prefix = new IpPrefix(prefixString);
1861 
1862         int optionLength;
1863         if (prefix.getPrefixLength() == 0) {
1864             optionLength = 1;
1865         } else if (prefix.getPrefixLength() <= 64) {
1866             optionLength = 2;
1867         } else {
1868             optionLength = 3;
1869         }
1870 
1871         packet.put((byte) ICMP6_ROUTE_INFO_OPTION_TYPE);  // Type
1872         packet.put((byte) optionLength);                  // Length in 8-byte units
1873         packet.put((byte) prefix.getPrefixLength());      // Prefix length
1874         packet.put((byte) 0b00011000);                    // Pref = high
1875         packet.putInt(lifetime);                          // Lifetime
1876 
1877         byte[] prefixBytes = prefix.getRawAddress();
1878         packet.put(prefixBytes, 0, (optionLength - 1) * 8);
1879     }
1880 
addPioOption(ByteBuffer packet, int valid, int preferred, String prefixString)1881     private void addPioOption(ByteBuffer packet, int valid, int preferred, String prefixString) {
1882         IpPrefix prefix = new IpPrefix(prefixString);
1883         packet.put((byte) ICMP6_PREFIX_OPTION_TYPE);  // Type
1884         packet.put((byte) 4);                         // Length in 8-byte units
1885         packet.put((byte) prefix.getPrefixLength());  // Prefix length
1886         packet.put((byte) 0b11000000);                // L = 1, A = 1
1887         packet.putInt(valid);
1888         packet.putInt(preferred);
1889         packet.putInt(0);                             // Reserved
1890         packet.put(prefix.getRawAddress());
1891     }
1892 
buildLargeRa()1893     private byte[] buildLargeRa() throws Exception {
1894         InetAddress src = InetAddress.getByName("fe80::1234:abcd");
1895 
1896         ByteBuffer packet = ByteBuffer.wrap(new byte[1514]);
1897         packet.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IPV6);
1898         packet.position(ETH_HEADER_LEN);
1899 
1900         packet.putInt(0x60012345);                                  // Version, tclass, flowlabel
1901         packet.putShort((short) 0);                                 // Payload length; updated later
1902         packet.put((byte) IPPROTO_ICMPV6);                          // Next header
1903         packet.put((byte) 0xff);                                    // Hop limit
1904         packet.put(src.getAddress());                               // Source address
1905         packet.put(IPV6_ALL_NODES_ADDRESS);                         // Destination address
1906 
1907         packet.put((byte) ICMP6_ROUTER_ADVERTISEMENT);              // Type
1908         packet.put((byte) 0);                                       // Code (0)
1909         packet.putShort((short) 0);                                 // Checksum (ignored)
1910         packet.put((byte) 64);                                      // Hop limit
1911         packet.put((byte) 0);                                       // M/O, reserved
1912         packet.putShort((short) 1800);                              // Router lifetime
1913         packet.putInt(30_000);                                      // Reachable time
1914         packet.putInt(1000);                                        // Retrans timer
1915 
1916         addRioOption(packet, 1200, "64:ff9b::/96");
1917         addRdnssOption(packet, 7200, "2001:db8:1::1", "2001:db8:1::2");
1918         addRioOption(packet, 2100, "2000::/3");
1919         addRioOption(packet, 2400, "::/0");
1920         addPioOption(packet, 600, 300, "2001:db8:a::/64");
1921         addRioOption(packet, 1500, "2001:db8:c:d::/64");
1922         addPioOption(packet, 86400, 43200, "fd95:d1e:12::/64");
1923 
1924         int length = packet.position();
1925         packet.putShort(IPV6_PAYLOAD_LENGTH_OFFSET, (short) length);
1926 
1927         // Don't pass the Ra constructor a packet that is longer than the actual RA.
1928         // This relies on the fact that all the relative writes to the byte buffer are at the end.
1929         byte[] packetArray = new byte[length];
1930         packet.rewind();
1931         packet.get(packetArray);
1932         return packetArray;
1933     }
1934 
1935     @Test
testRaToString()1936     public void testRaToString() throws Exception {
1937         MockIpClientCallback cb = new MockIpClientCallback();
1938         ApfConfiguration config = getDefaultConfig();
1939         TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog);
1940 
1941         byte[] packet = buildLargeRa();
1942         ApfFilter.Ra ra = apfFilter.new Ra(packet, packet.length);
1943         String expected = "RA fe80::1234:abcd -> ff02::1 1800s "
1944                 + "2001:db8:a::/64 600s/300s fd95:d1e:12::/64 86400s/43200s "
1945                 + "DNS 7200s 2001:db8:1::1 2001:db8:1::2 "
1946                 + "RIO 1200s 64:ff9b::/96 RIO 2100s 2000::/3 "
1947                 + "RIO 2400s ::/0 RIO 1500s 2001:db8:c:d::/64 ";
1948         assertEquals(expected, ra.toString());
1949     }
1950 
1951     // Verify that the last program pushed to the IpClient.Callback properly filters the
1952     // given packet for the given lifetime.
verifyRaLifetime(byte[] program, ByteBuffer packet, int lifetime)1953     private void verifyRaLifetime(byte[] program, ByteBuffer packet, int lifetime) {
1954         final int FRACTION_OF_LIFETIME = 6;
1955         final int ageLimit = lifetime / FRACTION_OF_LIFETIME;
1956 
1957         // Verify new program should drop RA for 1/6th its lifetime and pass afterwards.
1958         assertDrop(program, packet.array());
1959         assertDrop(program, packet.array(), ageLimit);
1960         assertPass(program, packet.array(), ageLimit + 1);
1961         assertPass(program, packet.array(), lifetime);
1962         // Verify RA checksum is ignored
1963         final short originalChecksum = packet.getShort(ICMP6_RA_CHECKSUM_OFFSET);
1964         packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)12345);
1965         assertDrop(program, packet.array());
1966         packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)-12345);
1967         assertDrop(program, packet.array());
1968         packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, originalChecksum);
1969 
1970         // Verify other changes to RA (e.g., a change in the source address) make it not match.
1971         final int offset = IPV6_SRC_ADDR_OFFSET + 5;
1972         final byte originalByte = packet.get(offset);
1973         packet.put(offset, (byte) (~originalByte));
1974         assertPass(program, packet.array());
1975         packet.put(offset, originalByte);
1976         assertDrop(program, packet.array());
1977     }
1978 
1979     // Test that when ApfFilter is shown the given packet, it generates a program to filter it
1980     // for the given lifetime.
verifyRaLifetime(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback, ByteBuffer packet, int lifetime)1981     private void verifyRaLifetime(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback,
1982             ByteBuffer packet, int lifetime) throws IOException, ErrnoException {
1983         // Verify new program generated if ApfFilter witnesses RA
1984         ipClientCallback.resetApfProgramWait();
1985         apfFilter.pretendPacketReceived(packet.array());
1986         byte[] program = ipClientCallback.getApfProgram();
1987         verifyRaLifetime(program, packet, lifetime);
1988     }
1989 
verifyRaEvent(RaEvent expected)1990     private void verifyRaEvent(RaEvent expected) {
1991         ArgumentCaptor<IpConnectivityLog.Event> captor =
1992                 ArgumentCaptor.forClass(IpConnectivityLog.Event.class);
1993         verify(mLog, atLeastOnce()).log(captor.capture());
1994         RaEvent got = lastRaEvent(captor.getAllValues());
1995         if (!raEventEquals(expected, got)) {
1996             assertEquals(expected, got);  // fail for printing an assertion error message.
1997         }
1998     }
1999 
lastRaEvent(List<IpConnectivityLog.Event> events)2000     private RaEvent lastRaEvent(List<IpConnectivityLog.Event> events) {
2001         RaEvent got = null;
2002         for (Parcelable ev : events) {
2003             if (ev instanceof RaEvent) {
2004                 got = (RaEvent) ev;
2005             }
2006         }
2007         return got;
2008     }
2009 
raEventEquals(RaEvent ev1, RaEvent ev2)2010     private boolean raEventEquals(RaEvent ev1, RaEvent ev2) {
2011         return (ev1 != null) && (ev2 != null)
2012                 && (ev1.routerLifetime == ev2.routerLifetime)
2013                 && (ev1.prefixValidLifetime == ev2.prefixValidLifetime)
2014                 && (ev1.prefixPreferredLifetime == ev2.prefixPreferredLifetime)
2015                 && (ev1.routeInfoLifetime == ev2.routeInfoLifetime)
2016                 && (ev1.rdnssLifetime == ev2.rdnssLifetime)
2017                 && (ev1.dnsslLifetime == ev2.dnsslLifetime);
2018     }
2019 
assertInvalidRa(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback, ByteBuffer packet)2020     private void assertInvalidRa(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback,
2021             ByteBuffer packet) throws IOException, ErrnoException {
2022         ipClientCallback.resetApfProgramWait();
2023         apfFilter.pretendPacketReceived(packet.array());
2024         ipClientCallback.assertNoProgramUpdate();
2025     }
2026 
makeBaseRaPacket()2027     private ByteBuffer makeBaseRaPacket() {
2028         ByteBuffer basePacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]);
2029         final int ROUTER_LIFETIME = 1000;
2030         final int VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET = ETH_HEADER_LEN;
2031         // IPv6, traffic class = 0, flow label = 0x12345
2032         final int VERSION_TRAFFIC_CLASS_FLOW_LABEL = 0x60012345;
2033 
2034         basePacket.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IPV6);
2035         basePacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET,
2036                 VERSION_TRAFFIC_CLASS_FLOW_LABEL);
2037         basePacket.put(IPV6_NEXT_HEADER_OFFSET, (byte) IPPROTO_ICMPV6);
2038         basePacket.put(ICMP6_TYPE_OFFSET, (byte) ICMP6_ROUTER_ADVERTISEMENT);
2039         basePacket.putShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET, (short) ROUTER_LIFETIME);
2040         basePacket.position(IPV6_DEST_ADDR_OFFSET);
2041         basePacket.put(IPV6_ALL_NODES_ADDRESS);
2042 
2043         return basePacket;
2044     }
2045 
2046     @Test
testApfFilterRa()2047     public void testApfFilterRa() throws Exception {
2048         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
2049         ApfConfiguration config = getDefaultConfig();
2050         config.multicastFilter = DROP_MULTICAST;
2051         config.ieee802_3Filter = DROP_802_3_FRAMES;
2052         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
2053         byte[] program = ipClientCallback.getApfProgram();
2054 
2055         final int ROUTER_LIFETIME = 1000;
2056         final int PREFIX_VALID_LIFETIME = 200;
2057         final int PREFIX_PREFERRED_LIFETIME = 100;
2058         final int RDNSS_LIFETIME  = 300;
2059         final int ROUTE_LIFETIME  = 400;
2060         // Note that lifetime of 2000 will be ignored in favor of shorter route lifetime of 1000.
2061         final int DNSSL_LIFETIME  = 2000;
2062         final int VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET = ETH_HEADER_LEN;
2063         // IPv6, traffic class = 0, flow label = 0x12345
2064         final int VERSION_TRAFFIC_CLASS_FLOW_LABEL = 0x60012345;
2065 
2066         // Verify RA is passed the first time
2067         ByteBuffer basePacket = makeBaseRaPacket();
2068         assertPass(program, basePacket.array());
2069 
2070         verifyRaLifetime(apfFilter, ipClientCallback, basePacket, ROUTER_LIFETIME);
2071         verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, -1));
2072 
2073         ByteBuffer newFlowLabelPacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]);
2074         basePacket.clear();
2075         newFlowLabelPacket.put(basePacket);
2076         // Check that changes are ignored in every byte of the flow label.
2077         newFlowLabelPacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET,
2078                 VERSION_TRAFFIC_CLASS_FLOW_LABEL + 0x11111);
2079 
2080         // Ensure zero-length options cause the packet to be silently skipped.
2081         // Do this before we test other packets. http://b/29586253
2082         ByteBuffer zeroLengthOptionPacket = ByteBuffer.wrap(
2083                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
2084         basePacket.clear();
2085         zeroLengthOptionPacket.put(basePacket);
2086         zeroLengthOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE);
2087         zeroLengthOptionPacket.put((byte)0);
2088         assertInvalidRa(apfFilter, ipClientCallback, zeroLengthOptionPacket);
2089 
2090         // Generate several RAs with different options and lifetimes, and verify when
2091         // ApfFilter is shown these packets, it generates programs to filter them for the
2092         // appropriate lifetime.
2093         ByteBuffer prefixOptionPacket = ByteBuffer.wrap(
2094                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_LEN]);
2095         basePacket.clear();
2096         prefixOptionPacket.put(basePacket);
2097         addPioOption(prefixOptionPacket, PREFIX_VALID_LIFETIME, PREFIX_PREFERRED_LIFETIME,
2098                 "2001:db8::/64");
2099         verifyRaLifetime(
2100                 apfFilter, ipClientCallback, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
2101         verifyRaEvent(new RaEvent(
2102                 ROUTER_LIFETIME, PREFIX_VALID_LIFETIME, PREFIX_PREFERRED_LIFETIME, -1, -1, -1));
2103 
2104         ByteBuffer rdnssOptionPacket = ByteBuffer.wrap(
2105                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN + 2 * IPV6_ADDR_LEN]);
2106         basePacket.clear();
2107         rdnssOptionPacket.put(basePacket);
2108         addRdnssOption(rdnssOptionPacket, RDNSS_LIFETIME,
2109                 "2001:4860:4860::8888", "2001:4860:4860::8844");
2110         verifyRaLifetime(apfFilter, ipClientCallback, rdnssOptionPacket, RDNSS_LIFETIME);
2111         verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, RDNSS_LIFETIME, -1));
2112 
2113         final int lowLifetime = 60;
2114         ByteBuffer lowLifetimeRdnssOptionPacket = ByteBuffer.wrap(
2115                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN + IPV6_ADDR_LEN]);
2116         basePacket.clear();
2117         lowLifetimeRdnssOptionPacket.put(basePacket);
2118         addRdnssOption(lowLifetimeRdnssOptionPacket, lowLifetime, "2620:fe::9");
2119         verifyRaLifetime(apfFilter, ipClientCallback, lowLifetimeRdnssOptionPacket,
2120                 ROUTER_LIFETIME);
2121         verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, lowLifetime, -1));
2122 
2123         ByteBuffer routeInfoOptionPacket = ByteBuffer.wrap(
2124                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN + IPV6_ADDR_LEN]);
2125         basePacket.clear();
2126         routeInfoOptionPacket.put(basePacket);
2127         addRioOption(routeInfoOptionPacket, ROUTE_LIFETIME, "64:ff9b::/96");
2128         verifyRaLifetime(apfFilter, ipClientCallback, routeInfoOptionPacket, ROUTE_LIFETIME);
2129         verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, ROUTE_LIFETIME, -1, -1));
2130 
2131         // Check that RIOs differing only in the first 4 bytes are different.
2132         ByteBuffer similarRouteInfoOptionPacket = ByteBuffer.wrap(
2133                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN + IPV6_ADDR_LEN]);
2134         basePacket.clear();
2135         similarRouteInfoOptionPacket.put(basePacket);
2136         addRioOption(similarRouteInfoOptionPacket, ROUTE_LIFETIME, "64:ff9b::/64");
2137         // Packet should be passed because it is different.
2138         program = ipClientCallback.getApfProgram();
2139         assertPass(program, similarRouteInfoOptionPacket.array());
2140 
2141         ByteBuffer dnsslOptionPacket = ByteBuffer.wrap(
2142                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
2143         basePacket.clear();
2144         dnsslOptionPacket.put(basePacket);
2145         dnsslOptionPacket.put((byte)ICMP6_DNSSL_OPTION_TYPE);
2146         dnsslOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
2147         dnsslOptionPacket.putInt(
2148                 ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, DNSSL_LIFETIME);
2149         verifyRaLifetime(apfFilter, ipClientCallback, dnsslOptionPacket, ROUTER_LIFETIME);
2150         verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, DNSSL_LIFETIME));
2151 
2152         ByteBuffer largeRaPacket = ByteBuffer.wrap(buildLargeRa());
2153         verifyRaLifetime(apfFilter, ipClientCallback, largeRaPacket, 300);
2154         verifyRaEvent(new RaEvent(1800, 600, 300, 1200, 7200, -1));
2155 
2156         // Verify that current program filters all the RAs (note: ApfFilter.MAX_RAS == 10).
2157         program = ipClientCallback.getApfProgram();
2158         verifyRaLifetime(program, basePacket, ROUTER_LIFETIME);
2159         verifyRaLifetime(program, newFlowLabelPacket, ROUTER_LIFETIME);
2160         verifyRaLifetime(program, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
2161         verifyRaLifetime(program, rdnssOptionPacket, RDNSS_LIFETIME);
2162         verifyRaLifetime(program, lowLifetimeRdnssOptionPacket, ROUTER_LIFETIME);
2163         verifyRaLifetime(program, routeInfoOptionPacket, ROUTE_LIFETIME);
2164         verifyRaLifetime(program, dnsslOptionPacket, ROUTER_LIFETIME);
2165         verifyRaLifetime(program, largeRaPacket, 300);
2166 
2167         apfFilter.shutdown();
2168     }
2169 
2170     @Test
testRaWithDifferentReachableTimeAndRetransTimer()2171     public void testRaWithDifferentReachableTimeAndRetransTimer() throws Exception {
2172         final MockIpClientCallback ipClientCallback = new MockIpClientCallback();
2173         final ApfConfiguration config = getDefaultConfig();
2174         config.multicastFilter = DROP_MULTICAST;
2175         config.ieee802_3Filter = DROP_802_3_FRAMES;
2176         final TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
2177         byte[] program = ipClientCallback.getApfProgram();
2178         final int RA_REACHABLE_TIME = 1800;
2179         final int RA_RETRANSMISSION_TIMER = 1234;
2180 
2181         // Create an Ra packet without options
2182         // Reachable time = 1800, retransmission timer = 1234
2183         ByteBuffer raPacket = makeBaseRaPacket();
2184         raPacket.position(ICMP6_RA_REACHABLE_TIME_OFFSET);
2185         raPacket.putInt(RA_REACHABLE_TIME);
2186         raPacket.putInt(RA_RETRANSMISSION_TIMER);
2187         // First RA passes filter
2188         assertPass(program, raPacket.array());
2189 
2190         // Assume apf is shown the given RA, it generates program to filter it.
2191         ipClientCallback.resetApfProgramWait();
2192         apfFilter.pretendPacketReceived(raPacket.array());
2193         program = ipClientCallback.getApfProgram();
2194         assertDrop(program, raPacket.array());
2195 
2196         // A packet with different reachable time should be passed.
2197         // Reachable time = 2300, retransmission timer = 1234
2198         raPacket.clear();
2199         raPacket.putInt(ICMP6_RA_REACHABLE_TIME_OFFSET, RA_REACHABLE_TIME + 500);
2200         assertPass(program, raPacket.array());
2201 
2202         // A packet with different retransmission timer should be passed.
2203         // Reachable time = 1800, retransmission timer = 2234
2204         raPacket.clear();
2205         raPacket.putInt(ICMP6_RA_REACHABLE_TIME_OFFSET, RA_REACHABLE_TIME);
2206         raPacket.putInt(ICMP6_RA_RETRANSMISSION_TIMER_OFFSET, RA_RETRANSMISSION_TIMER + 1000);
2207         assertPass(program, raPacket.array());
2208     }
2209 
2210     /**
2211      * Stage a file for testing, i.e. make it native accessible. Given a resource ID,
2212      * copy that resource into the app's data directory and return the path to it.
2213      */
stageFile(int rawId)2214     private String stageFile(int rawId) throws Exception {
2215         File file = new File(InstrumentationRegistry.getContext().getFilesDir(), "staged_file");
2216         new File(file.getParent()).mkdirs();
2217         InputStream in = null;
2218         OutputStream out = null;
2219         try {
2220             in = InstrumentationRegistry.getContext().getResources().openRawResource(rawId);
2221             out = new FileOutputStream(file);
2222             Streams.copy(in, out);
2223         } finally {
2224             if (in != null) in.close();
2225             if (out != null) out.close();
2226         }
2227         return file.getAbsolutePath();
2228     }
2229 
put(ByteBuffer buffer, int position, byte[] bytes)2230     private static void put(ByteBuffer buffer, int position, byte[] bytes) {
2231         final int original = buffer.position();
2232         buffer.position(position);
2233         buffer.put(bytes);
2234         buffer.position(original);
2235     }
2236 
2237     @Test
testRaParsing()2238     public void testRaParsing() throws Exception {
2239         final int maxRandomPacketSize = 512;
2240         final Random r = new Random();
2241         MockIpClientCallback cb = new MockIpClientCallback();
2242         ApfConfiguration config = getDefaultConfig();
2243         config.multicastFilter = DROP_MULTICAST;
2244         config.ieee802_3Filter = DROP_802_3_FRAMES;
2245         TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog);
2246         for (int i = 0; i < 1000; i++) {
2247             byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
2248             r.nextBytes(packet);
2249             try {
2250                 apfFilter.new Ra(packet, packet.length);
2251             } catch (ApfFilter.InvalidRaException e) {
2252             } catch (Exception e) {
2253                 throw new Exception("bad packet: " + HexDump.toHexString(packet), e);
2254             }
2255         }
2256     }
2257 
2258     @Test
testRaProcessing()2259     public void testRaProcessing() throws Exception {
2260         final int maxRandomPacketSize = 512;
2261         final Random r = new Random();
2262         MockIpClientCallback cb = new MockIpClientCallback();
2263         ApfConfiguration config = getDefaultConfig();
2264         config.multicastFilter = DROP_MULTICAST;
2265         config.ieee802_3Filter = DROP_802_3_FRAMES;
2266         TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog);
2267         for (int i = 0; i < 1000; i++) {
2268             byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
2269             r.nextBytes(packet);
2270             try {
2271                 apfFilter.processRa(packet, packet.length);
2272             } catch (Exception e) {
2273                 throw new Exception("bad packet: " + HexDump.toHexString(packet), e);
2274             }
2275         }
2276     }
2277 
2278     /**
2279      * Call the APF interpreter to run {@code program} on {@code packet} with persistent memory
2280      * segment {@data} pretending the filter was installed {@code filter_age} seconds ago.
2281      */
apfSimulate(byte[] program, byte[] packet, byte[] data, int filter_age)2282     private native static int apfSimulate(byte[] program, byte[] packet, byte[] data,
2283         int filter_age);
2284 
2285     /**
2286      * Compile a tcpdump human-readable filter (e.g. "icmp" or "tcp port 54") into a BPF
2287      * prorgam and return a human-readable dump of the BPF program identical to "tcpdump -d".
2288      */
compileToBpf(String filter)2289     private native static String compileToBpf(String filter);
2290 
2291     /**
2292      * Open packet capture file {@code pcap_filename} and filter the packets using tcpdump
2293      * human-readable filter (e.g. "icmp" or "tcp port 54") compiled to a BPF program and
2294      * at the same time using APF program {@code apf_program}.  Return {@code true} if
2295      * both APF and BPF programs filter out exactly the same packets.
2296      */
compareBpfApf(String filter, String pcap_filename, byte[] apf_program)2297     private native static boolean compareBpfApf(String filter, String pcap_filename,
2298             byte[] apf_program);
2299 
2300 
2301     /**
2302      * Open packet capture file {@code pcapFilename} and run it through APF filter. Then
2303      * checks whether all the packets are dropped and populates data[] {@code data} with
2304      * the APF counters.
2305      */
dropsAllPackets(byte[] program, byte[] data, String pcapFilename)2306     private native static boolean dropsAllPackets(byte[] program, byte[] data, String pcapFilename);
2307 
2308     @Test
testBroadcastAddress()2309     public void testBroadcastAddress() throws Exception {
2310         assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 0));
2311         assertEqualsIp("0.0.0.0", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 32));
2312         assertEqualsIp("0.0.3.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 22));
2313         assertEqualsIp("0.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 8));
2314 
2315         assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 0));
2316         assertEqualsIp("10.0.0.1", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 32));
2317         assertEqualsIp("10.0.0.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 24));
2318         assertEqualsIp("10.0.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 16));
2319     }
2320 
assertEqualsIp(String expected, int got)2321     public void assertEqualsIp(String expected, int got) throws Exception {
2322         int want = Inet4AddressUtils.inet4AddressToIntHTH(
2323                 (Inet4Address) InetAddresses.parseNumericAddress(expected));
2324         assertEquals(want, got);
2325     }
2326 }
2327