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.server.util.NetworkStackConstants.ICMPV6_ECHO_REQUEST_TYPE;
30 import static com.android.server.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.networkstack.apishim.NetworkInformationShimImpl;
71 import com.android.server.networkstack.tests.R;
72 import com.android.server.util.NetworkStackConstants;
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 
1060     private static final int ICMP6_TYPE_OFFSET           = IP_HEADER_OFFSET + IPV6_HEADER_LEN;
1061     private static final int ICMP6_ROUTER_SOLICITATION   = 133;
1062     private static final int ICMP6_ROUTER_ADVERTISEMENT  = 134;
1063     private static final int ICMP6_NEIGHBOR_SOLICITATION = 135;
1064     private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136;
1065 
1066     private static final int ICMP6_RA_HEADER_LEN = 16;
1067     private static final int ICMP6_RA_CHECKSUM_OFFSET =
1068             IP_HEADER_OFFSET + IPV6_HEADER_LEN + 2;
1069     private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET =
1070             IP_HEADER_OFFSET + IPV6_HEADER_LEN + 6;
1071     private static final int ICMP6_RA_REACHABLE_TIME_OFFSET =
1072             IP_HEADER_OFFSET + IPV6_HEADER_LEN + 8;
1073     private static final int ICMP6_RA_RETRANSMISSION_TIMER_OFFSET =
1074             IP_HEADER_OFFSET + IPV6_HEADER_LEN + 12;
1075     private static final int ICMP6_RA_OPTION_OFFSET =
1076             IP_HEADER_OFFSET + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN;
1077 
1078     private static final int ICMP6_PREFIX_OPTION_TYPE                      = 3;
1079     private static final int ICMP6_PREFIX_OPTION_LEN                       = 32;
1080     private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET     = 4;
1081     private static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET = 8;
1082 
1083     // From RFC6106: Recursive DNS Server option
1084     private static final int ICMP6_RDNSS_OPTION_TYPE = 25;
1085     // From RFC6106: DNS Search List option
1086     private static final int ICMP6_DNSSL_OPTION_TYPE = 31;
1087 
1088     // From RFC4191: Route Information option
1089     private static final int ICMP6_ROUTE_INFO_OPTION_TYPE = 24;
1090     // Above three options all have the same format:
1091     private static final int ICMP6_4_BYTE_OPTION_LEN      = 8;
1092     private static final int ICMP6_4_BYTE_LIFETIME_OFFSET = 4;
1093     private static final int ICMP6_4_BYTE_LIFETIME_LEN    = 4;
1094 
1095     private static final int UDP_HEADER_LEN              = 8;
1096     private static final int UDP_DESTINATION_PORT_OFFSET = ETH_HEADER_LEN + 22;
1097 
1098     private static final int DHCP_CLIENT_PORT       = 68;
1099     private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 48;
1100 
1101     private static final int ARP_HEADER_OFFSET          = ETH_HEADER_LEN;
1102     private static final byte[] ARP_IPV4_REQUEST_HEADER = {
1103             0, 1, // Hardware type: Ethernet (1)
1104             8, 0, // Protocol type: IP (0x0800)
1105             6,    // Hardware size: 6
1106             4,    // Protocol size: 4
1107             0, 1  // Opcode: request (1)
1108     };
1109     private static final byte[] ARP_IPV4_REPLY_HEADER = {
1110             0, 1, // Hardware type: Ethernet (1)
1111             8, 0, // Protocol type: IP (0x0800)
1112             6,    // Hardware size: 6
1113             4,    // Protocol size: 4
1114             0, 2  // Opcode: reply (2)
1115     };
1116     private static final int ARP_SOURCE_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 14;
1117     private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 24;
1118 
1119     private static final byte[] MOCK_IPV4_ADDR           = {10, 0, 0, 1};
1120     private static final byte[] MOCK_BROADCAST_IPV4_ADDR = {10, 0, 31, (byte) 255}; // prefix = 19
1121     private static final byte[] MOCK_MULTICAST_IPV4_ADDR = {(byte) 224, 0, 0, 1};
1122     private static final byte[] ANOTHER_IPV4_ADDR        = {10, 0, 0, 2};
1123     private static final byte[] IPV4_SOURCE_ADDR         = {10, 0, 0, 3};
1124     private static final byte[] ANOTHER_IPV4_SOURCE_ADDR = {(byte) 192, 0, 2, 1};
1125     private static final byte[] BUG_PROBE_SOURCE_ADDR1   = {0, 0, 1, 2};
1126     private static final byte[] BUG_PROBE_SOURCE_ADDR2   = {3, 4, 0, 0};
1127     private static final byte[] IPV4_ANY_HOST_ADDR       = {0, 0, 0, 0};
1128 
1129     // Helper to initialize a default apfFilter.
setupApfFilter( IpClientCallbacksWrapper ipClientCallback, ApfConfiguration config)1130     private ApfFilter setupApfFilter(
1131             IpClientCallbacksWrapper ipClientCallback, ApfConfiguration config) throws Exception {
1132         LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
1133         LinkProperties lp = new LinkProperties();
1134         lp.addLinkAddress(link);
1135         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
1136         apfFilter.setLinkProperties(lp);
1137         return apfFilter;
1138     }
1139 
setIpv4VersionFields(ByteBuffer packet)1140     private static void setIpv4VersionFields(ByteBuffer packet) {
1141         packet.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IP);
1142         packet.put(IP_HEADER_OFFSET, (byte) 0x45);
1143     }
1144 
setIpv6VersionFields(ByteBuffer packet)1145     private static void setIpv6VersionFields(ByteBuffer packet) {
1146         packet.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IPV6);
1147         packet.put(IP_HEADER_OFFSET, (byte) 0x60);
1148     }
1149 
makeIpv4Packet(int proto)1150     private static ByteBuffer makeIpv4Packet(int proto) {
1151         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1152         setIpv4VersionFields(packet);
1153         packet.put(IPV4_PROTOCOL_OFFSET, (byte) proto);
1154         return packet;
1155     }
1156 
makeIpv6Packet(int nextHeader)1157     private static ByteBuffer makeIpv6Packet(int nextHeader) {
1158         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1159         setIpv6VersionFields(packet);
1160         packet.put(IPV6_NEXT_HEADER_OFFSET, (byte) nextHeader);
1161         return packet;
1162     }
1163 
1164     @Test
testApfFilterIPv4()1165     public void testApfFilterIPv4() throws Exception {
1166         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
1167         LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
1168         LinkProperties lp = new LinkProperties();
1169         lp.addLinkAddress(link);
1170 
1171         ApfConfiguration config = getDefaultConfig();
1172         config.multicastFilter = DROP_MULTICAST;
1173         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
1174         apfFilter.setLinkProperties(lp);
1175 
1176         byte[] program = ipClientCallback.getApfProgram();
1177 
1178         // Verify empty packet of 100 zero bytes is passed
1179         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1180         assertPass(program, packet.array());
1181 
1182         // Verify unicast IPv4 packet is passed
1183         put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
1184         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1185         put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_IPV4_ADDR);
1186         assertPass(program, packet.array());
1187 
1188         // Verify L2 unicast to IPv4 broadcast addresses is dropped (b/30231088)
1189         put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
1190         assertDrop(program, packet.array());
1191         put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR);
1192         assertDrop(program, packet.array());
1193 
1194         // Verify multicast/broadcast IPv4, not DHCP to us, is dropped
1195         put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
1196         assertDrop(program, packet.array());
1197         packet.put(IP_HEADER_OFFSET, (byte) 0x45);
1198         assertDrop(program, packet.array());
1199         packet.put(IPV4_PROTOCOL_OFFSET, (byte)IPPROTO_UDP);
1200         assertDrop(program, packet.array());
1201         packet.putShort(UDP_DESTINATION_PORT_OFFSET, (short)DHCP_CLIENT_PORT);
1202         assertDrop(program, packet.array());
1203         put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_MULTICAST_IPV4_ADDR);
1204         assertDrop(program, packet.array());
1205         put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR);
1206         assertDrop(program, packet.array());
1207         put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
1208         assertDrop(program, packet.array());
1209 
1210         // Verify broadcast IPv4 DHCP to us is passed
1211         put(packet, DHCP_CLIENT_MAC_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
1212         assertPass(program, packet.array());
1213 
1214         // Verify unicast IPv4 DHCP to us is passed
1215         put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
1216         assertPass(program, packet.array());
1217 
1218         apfFilter.shutdown();
1219     }
1220 
1221     @Test
testApfFilterIPv6()1222     public void testApfFilterIPv6() throws Exception {
1223         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
1224         ApfConfiguration config = getDefaultConfig();
1225         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
1226         byte[] program = ipClientCallback.getApfProgram();
1227 
1228         // Verify empty IPv6 packet is passed
1229         ByteBuffer packet = makeIpv6Packet(IPPROTO_UDP);
1230         assertPass(program, packet.array());
1231 
1232         // Verify empty ICMPv6 packet is passed
1233         packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
1234         assertPass(program, packet.array());
1235 
1236         // Verify empty ICMPv6 NA packet is passed
1237         packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_NEIGHBOR_ANNOUNCEMENT);
1238         assertPass(program, packet.array());
1239 
1240         // Verify ICMPv6 NA to ff02::1 is dropped
1241         put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_NODES_ADDRESS);
1242         assertDrop(program, packet.array());
1243 
1244         // Verify ICMPv6 RS to any is dropped
1245         packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_SOLICITATION);
1246         assertDrop(program, packet.array());
1247         put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_ROUTERS_ADDRESS);
1248         assertDrop(program, packet.array());
1249 
1250         apfFilter.shutdown();
1251     }
1252 
1253     @Test
testApfFilterMulticast()1254     public void testApfFilterMulticast() throws Exception {
1255         final byte[] unicastIpv4Addr   = {(byte)192,0,2,63};
1256         final byte[] broadcastIpv4Addr = {(byte)192,0,2,(byte)255};
1257         final byte[] multicastIpv4Addr = {(byte)224,0,0,1};
1258         final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb};
1259 
1260         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
1261         LinkAddress link = new LinkAddress(InetAddress.getByAddress(unicastIpv4Addr), 24);
1262         LinkProperties lp = new LinkProperties();
1263         lp.addLinkAddress(link);
1264 
1265         ApfConfiguration config = getDefaultConfig();
1266         config.ieee802_3Filter = DROP_802_3_FRAMES;
1267         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
1268         apfFilter.setLinkProperties(lp);
1269 
1270         byte[] program = ipClientCallback.getApfProgram();
1271 
1272         // Construct IPv4 and IPv6 multicast packets.
1273         ByteBuffer mcastv4packet = makeIpv4Packet(IPPROTO_UDP);
1274         put(mcastv4packet, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr);
1275 
1276         ByteBuffer mcastv6packet = makeIpv6Packet(IPPROTO_UDP);
1277         put(mcastv6packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr);
1278 
1279         // Construct IPv4 broadcast packet.
1280         ByteBuffer bcastv4packet1 = makeIpv4Packet(IPPROTO_UDP);
1281         bcastv4packet1.put(ETH_BROADCAST_MAC_ADDRESS);
1282         bcastv4packet1.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1283         put(bcastv4packet1, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr);
1284 
1285         ByteBuffer bcastv4packet2 = makeIpv4Packet(IPPROTO_UDP);
1286         bcastv4packet2.put(ETH_BROADCAST_MAC_ADDRESS);
1287         bcastv4packet2.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1288         put(bcastv4packet2, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
1289 
1290         // Construct IPv4 broadcast with L2 unicast address packet (b/30231088).
1291         ByteBuffer bcastv4unicastl2packet = makeIpv4Packet(IPPROTO_UDP);
1292         bcastv4unicastl2packet.put(TestApfFilter.MOCK_MAC_ADDR);
1293         bcastv4unicastl2packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1294         put(bcastv4unicastl2packet, IPV4_DEST_ADDR_OFFSET, broadcastIpv4Addr);
1295 
1296         // Verify initially disabled multicast filter is off
1297         assertPass(program, mcastv4packet.array());
1298         assertPass(program, mcastv6packet.array());
1299         assertPass(program, bcastv4packet1.array());
1300         assertPass(program, bcastv4packet2.array());
1301         assertPass(program, bcastv4unicastl2packet.array());
1302 
1303         // Turn on multicast filter and verify it works
1304         ipClientCallback.resetApfProgramWait();
1305         apfFilter.setMulticastFilter(true);
1306         program = ipClientCallback.getApfProgram();
1307         assertDrop(program, mcastv4packet.array());
1308         assertDrop(program, mcastv6packet.array());
1309         assertDrop(program, bcastv4packet1.array());
1310         assertDrop(program, bcastv4packet2.array());
1311         assertDrop(program, bcastv4unicastl2packet.array());
1312 
1313         // Turn off multicast filter and verify it's off
1314         ipClientCallback.resetApfProgramWait();
1315         apfFilter.setMulticastFilter(false);
1316         program = ipClientCallback.getApfProgram();
1317         assertPass(program, mcastv4packet.array());
1318         assertPass(program, mcastv6packet.array());
1319         assertPass(program, bcastv4packet1.array());
1320         assertPass(program, bcastv4packet2.array());
1321         assertPass(program, bcastv4unicastl2packet.array());
1322 
1323         // Verify it can be initialized to on
1324         ipClientCallback.resetApfProgramWait();
1325         apfFilter.shutdown();
1326         config.multicastFilter = DROP_MULTICAST;
1327         config.ieee802_3Filter = DROP_802_3_FRAMES;
1328         apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
1329         apfFilter.setLinkProperties(lp);
1330         program = ipClientCallback.getApfProgram();
1331         assertDrop(program, mcastv4packet.array());
1332         assertDrop(program, mcastv6packet.array());
1333         assertDrop(program, bcastv4packet1.array());
1334         assertDrop(program, bcastv4unicastl2packet.array());
1335 
1336         // Verify that ICMPv6 multicast is not dropped.
1337         mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
1338         assertPass(program, mcastv6packet.array());
1339 
1340         apfFilter.shutdown();
1341     }
1342 
1343     @Test
testApfFilterMulticastPingWhileDozing()1344     public void testApfFilterMulticastPingWhileDozing() throws Exception {
1345         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
1346         ApfFilter apfFilter = setupApfFilter(ipClientCallback, getDefaultConfig());
1347 
1348         // Construct a multicast ICMPv6 ECHO request.
1349         final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb};
1350         ByteBuffer packet = makeIpv6Packet(IPPROTO_ICMPV6);
1351         packet.put(ICMP6_TYPE_OFFSET, (byte)ICMPV6_ECHO_REQUEST_TYPE);
1352         put(packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr);
1353 
1354         // Normally, we let multicast pings alone...
1355         assertPass(ipClientCallback.getApfProgram(), packet.array());
1356 
1357         // ...and even while dozing...
1358         apfFilter.setDozeMode(true);
1359         assertPass(ipClientCallback.getApfProgram(), packet.array());
1360 
1361         // ...but when the multicast filter is also enabled, drop the multicast pings to save power.
1362         apfFilter.setMulticastFilter(true);
1363         assertDrop(ipClientCallback.getApfProgram(), packet.array());
1364 
1365         // However, we should still let through all other ICMPv6 types.
1366         ByteBuffer raPacket = ByteBuffer.wrap(packet.array().clone());
1367         setIpv6VersionFields(packet);
1368         packet.put(IPV6_NEXT_HEADER_OFFSET, (byte) IPPROTO_ICMPV6);
1369         raPacket.put(ICMP6_TYPE_OFFSET, (byte) NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT);
1370         assertPass(ipClientCallback.getApfProgram(), raPacket.array());
1371 
1372         // Now wake up from doze mode to ensure that we no longer drop the packets.
1373         // (The multicast filter is still enabled at this point).
1374         apfFilter.setDozeMode(false);
1375         assertPass(ipClientCallback.getApfProgram(), packet.array());
1376 
1377         apfFilter.shutdown();
1378     }
1379 
1380     @Test
testApfFilter802_3()1381     public void testApfFilter802_3() throws Exception {
1382         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
1383         ApfConfiguration config = getDefaultConfig();
1384         ApfFilter apfFilter = setupApfFilter(ipClientCallback, config);
1385         byte[] program = ipClientCallback.getApfProgram();
1386 
1387         // Verify empty packet of 100 zero bytes is passed
1388         // Note that eth-type = 0 makes it an IEEE802.3 frame
1389         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1390         assertPass(program, packet.array());
1391 
1392         // Verify empty packet with IPv4 is passed
1393         setIpv4VersionFields(packet);
1394         assertPass(program, packet.array());
1395 
1396         // Verify empty IPv6 packet is passed
1397         setIpv6VersionFields(packet);
1398         assertPass(program, packet.array());
1399 
1400         // Now turn on the filter
1401         ipClientCallback.resetApfProgramWait();
1402         apfFilter.shutdown();
1403         config.ieee802_3Filter = DROP_802_3_FRAMES;
1404         apfFilter = setupApfFilter(ipClientCallback, config);
1405         program = ipClientCallback.getApfProgram();
1406 
1407         // Verify that IEEE802.3 frame is dropped
1408         // In this case ethtype is used for payload length
1409         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)(100 - 14));
1410         assertDrop(program, packet.array());
1411 
1412         // Verify that IPv4 (as example of Ethernet II) frame will pass
1413         setIpv4VersionFields(packet);
1414         assertPass(program, packet.array());
1415 
1416         // Verify that IPv6 (as example of Ethernet II) frame will pass
1417         setIpv6VersionFields(packet);
1418         assertPass(program, packet.array());
1419 
1420         apfFilter.shutdown();
1421     }
1422 
1423     @Test
testApfFilterEthTypeBL()1424     public void testApfFilterEthTypeBL() throws Exception {
1425         final int[] emptyBlackList = {};
1426         final int[] ipv4BlackList = {ETH_P_IP};
1427         final int[] ipv4Ipv6BlackList = {ETH_P_IP, ETH_P_IPV6};
1428 
1429         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
1430         ApfConfiguration config = getDefaultConfig();
1431         ApfFilter apfFilter = setupApfFilter(ipClientCallback, config);
1432         byte[] program = ipClientCallback.getApfProgram();
1433 
1434         // Verify empty packet of 100 zero bytes is passed
1435         // Note that eth-type = 0 makes it an IEEE802.3 frame
1436         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1437         assertPass(program, packet.array());
1438 
1439         // Verify empty packet with IPv4 is passed
1440         setIpv4VersionFields(packet);
1441         assertPass(program, packet.array());
1442 
1443         // Verify empty IPv6 packet is passed
1444         setIpv6VersionFields(packet);
1445         assertPass(program, packet.array());
1446 
1447         // Now add IPv4 to the black list
1448         ipClientCallback.resetApfProgramWait();
1449         apfFilter.shutdown();
1450         config.ethTypeBlackList = ipv4BlackList;
1451         apfFilter = setupApfFilter(ipClientCallback, config);
1452         program = ipClientCallback.getApfProgram();
1453 
1454         // Verify that IPv4 frame will be dropped
1455         setIpv4VersionFields(packet);
1456         assertDrop(program, packet.array());
1457 
1458         // Verify that IPv6 frame will pass
1459         setIpv6VersionFields(packet);
1460         assertPass(program, packet.array());
1461 
1462         // Now let us have both IPv4 and IPv6 in the black list
1463         ipClientCallback.resetApfProgramWait();
1464         apfFilter.shutdown();
1465         config.ethTypeBlackList = ipv4Ipv6BlackList;
1466         apfFilter = setupApfFilter(ipClientCallback, config);
1467         program = ipClientCallback.getApfProgram();
1468 
1469         // Verify that IPv4 frame will be dropped
1470         setIpv4VersionFields(packet);
1471         assertDrop(program, packet.array());
1472 
1473         // Verify that IPv6 frame will be dropped
1474         setIpv6VersionFields(packet);
1475         assertDrop(program, packet.array());
1476 
1477         apfFilter.shutdown();
1478     }
1479 
getProgram(MockIpClientCallback cb, ApfFilter filter, LinkProperties lp)1480     private byte[] getProgram(MockIpClientCallback cb, ApfFilter filter, LinkProperties lp) {
1481         cb.resetApfProgramWait();
1482         filter.setLinkProperties(lp);
1483         return cb.getApfProgram();
1484     }
1485 
verifyArpFilter(byte[] program, int filterResult)1486     private void verifyArpFilter(byte[] program, int filterResult) {
1487         // Verify ARP request packet
1488         assertPass(program, arpRequestBroadcast(MOCK_IPV4_ADDR));
1489         assertVerdict(filterResult, program, arpRequestBroadcast(ANOTHER_IPV4_ADDR));
1490         assertDrop(program, arpRequestBroadcast(IPV4_ANY_HOST_ADDR));
1491 
1492         // Verify ARP reply packets from different source ip
1493         assertDrop(program, arpReply(IPV4_ANY_HOST_ADDR, IPV4_ANY_HOST_ADDR));
1494         assertPass(program, arpReply(ANOTHER_IPV4_SOURCE_ADDR, IPV4_ANY_HOST_ADDR));
1495         assertPass(program, arpReply(BUG_PROBE_SOURCE_ADDR1, IPV4_ANY_HOST_ADDR));
1496         assertPass(program, arpReply(BUG_PROBE_SOURCE_ADDR2, IPV4_ANY_HOST_ADDR));
1497 
1498         // Verify unicast ARP reply packet is always accepted.
1499         assertPass(program, arpReply(IPV4_SOURCE_ADDR, MOCK_IPV4_ADDR));
1500         assertPass(program, arpReply(IPV4_SOURCE_ADDR, ANOTHER_IPV4_ADDR));
1501         assertPass(program, arpReply(IPV4_SOURCE_ADDR, IPV4_ANY_HOST_ADDR));
1502 
1503         // Verify GARP reply packets are always filtered
1504         assertDrop(program, garpReply());
1505     }
1506 
1507     @Test
testApfFilterArp()1508     public void testApfFilterArp() throws Exception {
1509         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
1510         ApfConfiguration config = getDefaultConfig();
1511         config.multicastFilter = DROP_MULTICAST;
1512         config.ieee802_3Filter = DROP_802_3_FRAMES;
1513         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
1514 
1515         // Verify initially ARP request filter is off, and GARP filter is on.
1516         verifyArpFilter(ipClientCallback.getApfProgram(), PASS);
1517 
1518         // Inform ApfFilter of our address and verify ARP filtering is on
1519         LinkAddress linkAddress = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 24);
1520         LinkProperties lp = new LinkProperties();
1521         assertTrue(lp.addLinkAddress(linkAddress));
1522         verifyArpFilter(getProgram(ipClientCallback, apfFilter, lp), DROP);
1523 
1524         // Inform ApfFilter of loss of IP and verify ARP filtering is off
1525         verifyArpFilter(getProgram(ipClientCallback, apfFilter, new LinkProperties()), PASS);
1526 
1527         apfFilter.shutdown();
1528     }
1529 
arpReply(byte[] sip, byte[] tip)1530     private static byte[] arpReply(byte[] sip, byte[] tip) {
1531         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1532         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
1533         put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
1534         put(packet, ARP_SOURCE_IP_ADDRESS_OFFSET, sip);
1535         put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip);
1536         return packet.array();
1537     }
1538 
arpRequestBroadcast(byte[] tip)1539     private static byte[] arpRequestBroadcast(byte[] tip) {
1540         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1541         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
1542         put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
1543         put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REQUEST_HEADER);
1544         put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip);
1545         return packet.array();
1546     }
1547 
garpReply()1548     private static byte[] garpReply() {
1549         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1550         packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
1551         put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
1552         put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
1553         put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, IPV4_ANY_HOST_ADDR);
1554         return packet.array();
1555     }
1556 
1557     private static final byte[] IPV4_KEEPALIVE_SRC_ADDR = {10, 0, 0, 5};
1558     private static final byte[] IPV4_KEEPALIVE_DST_ADDR = {10, 0, 0, 6};
1559     private static final byte[] IPV4_ANOTHER_ADDR = {10, 0 , 0, 7};
1560     private static final byte[] IPV6_KEEPALIVE_SRC_ADDR =
1561             {(byte) 0x24, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xfa, (byte) 0xf1};
1562     private static final byte[] IPV6_KEEPALIVE_DST_ADDR =
1563             {(byte) 0x24, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xfa, (byte) 0xf2};
1564     private static final byte[] IPV6_ANOTHER_ADDR =
1565             {(byte) 0x24, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xfa, (byte) 0xf5};
1566 
1567     @Test
testApfFilterKeepaliveAck()1568     public void testApfFilterKeepaliveAck() throws Exception {
1569         final MockIpClientCallback cb = new MockIpClientCallback();
1570         final ApfConfiguration config = getDefaultConfig();
1571         config.multicastFilter = DROP_MULTICAST;
1572         config.ieee802_3Filter = DROP_802_3_FRAMES;
1573         final TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog);
1574         byte[] program;
1575         final int srcPort = 12345;
1576         final int dstPort = 54321;
1577         final int seqNum = 2123456789;
1578         final int ackNum = 1234567890;
1579         final int anotherSrcPort = 23456;
1580         final int anotherDstPort = 65432;
1581         final int anotherSeqNum = 2123456780;
1582         final int anotherAckNum = 1123456789;
1583         final int slot1 = 1;
1584         final int slot2 = 2;
1585         final int window = 14480;
1586         final int windowScale = 4;
1587 
1588         // src: 10.0.0.5, port: 12345
1589         // dst: 10.0.0.6, port: 54321
1590         InetAddress srcAddr = InetAddress.getByAddress(IPV4_KEEPALIVE_SRC_ADDR);
1591         InetAddress dstAddr = InetAddress.getByAddress(IPV4_KEEPALIVE_DST_ADDR);
1592 
1593         final TcpKeepalivePacketDataParcelable parcel = new TcpKeepalivePacketDataParcelable();
1594         parcel.srcAddress = srcAddr.getAddress();
1595         parcel.srcPort = srcPort;
1596         parcel.dstAddress = dstAddr.getAddress();
1597         parcel.dstPort = dstPort;
1598         parcel.seq = seqNum;
1599         parcel.ack = ackNum;
1600 
1601         apfFilter.addTcpKeepalivePacketFilter(slot1, parcel);
1602         program = cb.getApfProgram();
1603 
1604         // Verify IPv4 keepalive ack packet is dropped
1605         // src: 10.0.0.6, port: 54321
1606         // dst: 10.0.0.5, port: 12345
1607         assertDrop(program,
1608                 ipv4TcpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
1609                         dstPort, srcPort, ackNum, seqNum + 1, 0 /* dataLength */));
1610         // Verify IPv4 non-keepalive ack packet from the same source address is passed
1611         assertPass(program,
1612                 ipv4TcpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
1613                         dstPort, srcPort, ackNum + 100, seqNum, 0 /* dataLength */));
1614         assertPass(program,
1615                 ipv4TcpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
1616                         dstPort, srcPort, ackNum, seqNum + 1, 10 /* dataLength */));
1617         // Verify IPv4 packet from another address is passed
1618         assertPass(program,
1619                 ipv4TcpPacket(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR, anotherSrcPort,
1620                         anotherDstPort, anotherSeqNum, anotherAckNum, 0 /* dataLength */));
1621 
1622         // Remove IPv4 keepalive filter
1623         apfFilter.removeKeepalivePacketFilter(slot1);
1624 
1625         try {
1626             // src: 2404:0:0:0:0:0:faf1, port: 12345
1627             // dst: 2404:0:0:0:0:0:faf2, port: 54321
1628             srcAddr = InetAddress.getByAddress(IPV6_KEEPALIVE_SRC_ADDR);
1629             dstAddr = InetAddress.getByAddress(IPV6_KEEPALIVE_DST_ADDR);
1630 
1631             final TcpKeepalivePacketDataParcelable ipv6Parcel =
1632                     new TcpKeepalivePacketDataParcelable();
1633             ipv6Parcel.srcAddress = srcAddr.getAddress();
1634             ipv6Parcel.srcPort = srcPort;
1635             ipv6Parcel.dstAddress = dstAddr.getAddress();
1636             ipv6Parcel.dstPort = dstPort;
1637             ipv6Parcel.seq = seqNum;
1638             ipv6Parcel.ack = ackNum;
1639 
1640             apfFilter.addTcpKeepalivePacketFilter(slot1, ipv6Parcel);
1641             program = cb.getApfProgram();
1642 
1643             // Verify IPv6 keepalive ack packet is dropped
1644             // src: 2404:0:0:0:0:0:faf2, port: 54321
1645             // dst: 2404:0:0:0:0:0:faf1, port: 12345
1646             assertDrop(program,
1647                     ipv6TcpPacket(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR,
1648                             dstPort, srcPort, ackNum, seqNum + 1));
1649             // Verify IPv6 non-keepalive ack packet from the same source address is passed
1650             assertPass(program,
1651                     ipv6TcpPacket(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR,
1652                             dstPort, srcPort, ackNum + 100, seqNum));
1653             // Verify IPv6 packet from another address is passed
1654             assertPass(program,
1655                     ipv6TcpPacket(IPV6_ANOTHER_ADDR, IPV6_KEEPALIVE_SRC_ADDR, anotherSrcPort,
1656                             anotherDstPort, anotherSeqNum, anotherAckNum));
1657 
1658             // Remove IPv6 keepalive filter
1659             apfFilter.removeKeepalivePacketFilter(slot1);
1660 
1661             // Verify multiple filters
1662             apfFilter.addTcpKeepalivePacketFilter(slot1, parcel);
1663             apfFilter.addTcpKeepalivePacketFilter(slot2, ipv6Parcel);
1664             program = cb.getApfProgram();
1665 
1666             // Verify IPv4 keepalive ack packet is dropped
1667             // src: 10.0.0.6, port: 54321
1668             // dst: 10.0.0.5, port: 12345
1669             assertDrop(program,
1670                     ipv4TcpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
1671                             dstPort, srcPort, ackNum, seqNum + 1, 0 /* dataLength */));
1672             // Verify IPv4 non-keepalive ack packet from the same source address is passed
1673             assertPass(program,
1674                     ipv4TcpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
1675                             dstPort, srcPort, ackNum + 100, seqNum, 0 /* dataLength */));
1676             // Verify IPv4 packet from another address is passed
1677             assertPass(program,
1678                     ipv4TcpPacket(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR, anotherSrcPort,
1679                             anotherDstPort, anotherSeqNum, anotherAckNum, 0 /* dataLength */));
1680 
1681             // Verify IPv6 keepalive ack packet is dropped
1682             // src: 2404:0:0:0:0:0:faf2, port: 54321
1683             // dst: 2404:0:0:0:0:0:faf1, port: 12345
1684             assertDrop(program,
1685                     ipv6TcpPacket(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR,
1686                             dstPort, srcPort, ackNum, seqNum + 1));
1687             // Verify IPv6 non-keepalive ack packet from the same source address is passed
1688             assertPass(program,
1689                     ipv6TcpPacket(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR,
1690                             dstPort, srcPort, ackNum + 100, seqNum));
1691             // Verify IPv6 packet from another address is passed
1692             assertPass(program,
1693                     ipv6TcpPacket(IPV6_ANOTHER_ADDR, IPV6_KEEPALIVE_SRC_ADDR, anotherSrcPort,
1694                             anotherDstPort, anotherSeqNum, anotherAckNum));
1695 
1696             // Remove keepalive filters
1697             apfFilter.removeKeepalivePacketFilter(slot1);
1698             apfFilter.removeKeepalivePacketFilter(slot2);
1699         } catch (UnsupportedOperationException e) {
1700             // TODO: support V6 packets
1701         }
1702 
1703         program = cb.getApfProgram();
1704 
1705         // Verify IPv4, IPv6 packets are passed
1706         assertPass(program,
1707                 ipv4TcpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
1708                         dstPort, srcPort, ackNum, seqNum + 1, 0 /* dataLength */));
1709         assertPass(program,
1710                 ipv6TcpPacket(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR,
1711                         dstPort, srcPort, ackNum, seqNum + 1));
1712         assertPass(program,
1713                 ipv4TcpPacket(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR, srcPort,
1714                         dstPort, anotherSeqNum, anotherAckNum, 0 /* dataLength */));
1715         assertPass(program,
1716                 ipv6TcpPacket(IPV6_ANOTHER_ADDR, IPV6_KEEPALIVE_SRC_ADDR, srcPort,
1717                         dstPort, anotherSeqNum, anotherAckNum));
1718 
1719         apfFilter.shutdown();
1720     }
1721 
ipv4TcpPacket(byte[] sip, byte[] dip, int sport, int dport, int seq, int ack, int dataLength)1722     private static byte[] ipv4TcpPacket(byte[] sip, byte[] dip, int sport,
1723             int dport, int seq, int ack, int dataLength) {
1724         final int totalLength = dataLength + IPV4_HEADER_LEN + IPV4_TCP_HEADER_LEN;
1725 
1726         ByteBuffer packet = ByteBuffer.wrap(new byte[totalLength + ETH_HEADER_LEN]);
1727 
1728         // Ethertype and IPv4 header
1729         setIpv4VersionFields(packet);
1730         packet.putShort(IPV4_TOTAL_LENGTH_OFFSET, (short) totalLength);
1731         packet.put(IPV4_PROTOCOL_OFFSET, (byte) IPPROTO_TCP);
1732         put(packet, IPV4_SRC_ADDR_OFFSET, sip);
1733         put(packet, IPV4_DEST_ADDR_OFFSET, dip);
1734         packet.putShort(IPV4_TCP_SRC_PORT_OFFSET, (short) sport);
1735         packet.putShort(IPV4_TCP_DEST_PORT_OFFSET, (short) dport);
1736         packet.putInt(IPV4_TCP_SEQ_NUM_OFFSET, seq);
1737         packet.putInt(IPV4_TCP_ACK_NUM_OFFSET, ack);
1738 
1739         // TCP header length 5(20 bytes), reserved 3 bits, NS=0
1740         packet.put(IPV4_TCP_HEADER_LENGTH_OFFSET, (byte) 0x50);
1741         // TCP flags: ACK set
1742         packet.put(IPV4_TCP_HEADER_FLAG_OFFSET, (byte) 0x10);
1743         return packet.array();
1744     }
1745 
ipv6TcpPacket(byte[] sip, byte[] tip, int sport, int dport, int seq, int ack)1746     private static byte[] ipv6TcpPacket(byte[] sip, byte[] tip, int sport,
1747             int dport, int seq, int ack) {
1748         ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1749         setIpv6VersionFields(packet);
1750         packet.put(IPV6_NEXT_HEADER_OFFSET, (byte) IPPROTO_TCP);
1751         put(packet, IPV6_SRC_ADDR_OFFSET, sip);
1752         put(packet, IPV6_DEST_ADDR_OFFSET, tip);
1753         packet.putShort(IPV6_TCP_SRC_PORT_OFFSET, (short) sport);
1754         packet.putShort(IPV6_TCP_DEST_PORT_OFFSET, (short) dport);
1755         packet.putInt(IPV6_TCP_SEQ_NUM_OFFSET, seq);
1756         packet.putInt(IPV6_TCP_ACK_NUM_OFFSET, ack);
1757         return packet.array();
1758     }
1759 
1760     @Test
testApfFilterNattKeepalivePacket()1761     public void testApfFilterNattKeepalivePacket() throws Exception {
1762         final MockIpClientCallback cb = new MockIpClientCallback();
1763         final ApfConfiguration config = getDefaultConfig();
1764         config.multicastFilter = DROP_MULTICAST;
1765         config.ieee802_3Filter = DROP_802_3_FRAMES;
1766         final TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog);
1767         byte[] program;
1768         final int srcPort = 1024;
1769         final int dstPort = 4500;
1770         final int slot1 = 1;
1771         // NAT-T keepalive
1772         final byte[] kaPayload = {(byte) 0xff};
1773         final byte[] nonKaPayload = {(byte) 0xfe};
1774 
1775         // src: 10.0.0.5, port: 1024
1776         // dst: 10.0.0.6, port: 4500
1777         InetAddress srcAddr = InetAddress.getByAddress(IPV4_KEEPALIVE_SRC_ADDR);
1778         InetAddress dstAddr = InetAddress.getByAddress(IPV4_KEEPALIVE_DST_ADDR);
1779 
1780         final NattKeepalivePacketDataParcelable parcel = new NattKeepalivePacketDataParcelable();
1781         parcel.srcAddress = srcAddr.getAddress();
1782         parcel.srcPort = srcPort;
1783         parcel.dstAddress = dstAddr.getAddress();
1784         parcel.dstPort = dstPort;
1785 
1786         apfFilter.addNattKeepalivePacketFilter(slot1, parcel);
1787         program = cb.getApfProgram();
1788 
1789         // Verify IPv4 keepalive packet is dropped
1790         // src: 10.0.0.6, port: 4500
1791         // dst: 10.0.0.5, port: 1024
1792         byte[] pkt = ipv4UdpPacket(IPV4_KEEPALIVE_DST_ADDR,
1793                     IPV4_KEEPALIVE_SRC_ADDR, dstPort, srcPort, 1 /* dataLength */);
1794         System.arraycopy(kaPayload, 0, pkt, IPV4_UDP_PAYLOAD_OFFSET, kaPayload.length);
1795         assertDrop(program, pkt);
1796 
1797         // Verify a packet with payload length 1 byte but it is not 0xff will pass the filter.
1798         System.arraycopy(nonKaPayload, 0, pkt, IPV4_UDP_PAYLOAD_OFFSET, nonKaPayload.length);
1799         assertPass(program, pkt);
1800 
1801         // Verify IPv4 non-keepalive response packet from the same source address is passed
1802         assertPass(program,
1803                 ipv4UdpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
1804                         dstPort, srcPort, 10 /* dataLength */));
1805 
1806         // Verify IPv4 non-keepalive response packet from other source address is passed
1807         assertPass(program,
1808                 ipv4UdpPacket(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
1809                         dstPort, srcPort, 10 /* dataLength */));
1810 
1811         apfFilter.removeKeepalivePacketFilter(slot1);
1812         apfFilter.shutdown();
1813     }
1814 
ipv4UdpPacket(byte[] sip, byte[] dip, int sport, int dport, int dataLength)1815     private static byte[] ipv4UdpPacket(byte[] sip, byte[] dip, int sport,
1816             int dport, int dataLength) {
1817         final int totalLength = dataLength + IPV4_HEADER_LEN + UDP_HEADER_LEN;
1818         final int udpLength = UDP_HEADER_LEN + dataLength;
1819         ByteBuffer packet = ByteBuffer.wrap(new byte[totalLength + ETH_HEADER_LEN]);
1820 
1821         // Ethertype and IPv4 header
1822         setIpv4VersionFields(packet);
1823         packet.putShort(IPV4_TOTAL_LENGTH_OFFSET, (short) totalLength);
1824         packet.put(IPV4_PROTOCOL_OFFSET, (byte) IPPROTO_UDP);
1825         put(packet, IPV4_SRC_ADDR_OFFSET, sip);
1826         put(packet, IPV4_DEST_ADDR_OFFSET, dip);
1827         packet.putShort(IPV4_UDP_SRC_PORT_OFFSET, (short) sport);
1828         packet.putShort(IPV4_UDP_DEST_PORT_OFFSET, (short) dport);
1829         packet.putShort(IPV4_UDP_LENGTH_OFFSET, (short) udpLength);
1830 
1831         return packet.array();
1832     }
1833 
addRdnssOption(ByteBuffer packet, int lifetime, String... servers)1834     private void addRdnssOption(ByteBuffer packet, int lifetime, String... servers)
1835             throws Exception {
1836         int optionLength = 1 + 2 * servers.length;   // In 8-byte units
1837         packet.put((byte) ICMP6_RDNSS_OPTION_TYPE);  // Type
1838         packet.put((byte) optionLength);             // Length
1839         packet.putShort((short) 0);                  // Reserved
1840         packet.putInt(lifetime);                     // Lifetime
1841         for (String server : servers) {
1842             packet.put(InetAddress.getByName(server).getAddress());
1843         }
1844     }
1845 
addRioOption(ByteBuffer packet, int lifetime, String prefixString)1846     private void addRioOption(ByteBuffer packet, int lifetime, String prefixString)
1847             throws Exception {
1848         IpPrefix prefix = new IpPrefix(prefixString);
1849 
1850         int optionLength;
1851         if (prefix.getPrefixLength() == 0) {
1852             optionLength = 1;
1853         } else if (prefix.getPrefixLength() <= 64) {
1854             optionLength = 2;
1855         } else {
1856             optionLength = 3;
1857         }
1858 
1859         packet.put((byte) ICMP6_ROUTE_INFO_OPTION_TYPE);  // Type
1860         packet.put((byte) optionLength);                  // Length in 8-byte units
1861         packet.put((byte) prefix.getPrefixLength());      // Prefix length
1862         packet.put((byte) 0b00011000);                    // Pref = high
1863         packet.putInt(lifetime);                          // Lifetime
1864 
1865         byte[] prefixBytes = prefix.getRawAddress();
1866         packet.put(prefixBytes, 0, (optionLength - 1) * 8);
1867     }
1868 
addPioOption(ByteBuffer packet, int valid, int preferred, String prefixString)1869     private void addPioOption(ByteBuffer packet, int valid, int preferred, String prefixString) {
1870         IpPrefix prefix = new IpPrefix(prefixString);
1871         packet.put((byte) ICMP6_PREFIX_OPTION_TYPE);  // Type
1872         packet.put((byte) 4);                         // Length in 8-byte units
1873         packet.put((byte) prefix.getPrefixLength());  // Prefix length
1874         packet.put((byte) 0b11000000);                // L = 1, A = 1
1875         packet.putInt(valid);
1876         packet.putInt(preferred);
1877         packet.putInt(0);                             // Reserved
1878         packet.put(prefix.getRawAddress());
1879     }
1880 
buildLargeRa()1881     private byte[] buildLargeRa() throws Exception {
1882         InetAddress src = InetAddress.getByName("fe80::1234:abcd");
1883 
1884         ByteBuffer packet = ByteBuffer.wrap(new byte[1514]);
1885         packet.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IPV6);
1886         packet.position(ETH_HEADER_LEN);
1887 
1888         packet.putInt(0x60012345);                                  // Version, tclass, flowlabel
1889         packet.putShort((short) 0);                                 // Payload length; updated later
1890         packet.put((byte) IPPROTO_ICMPV6);                          // Next header
1891         packet.put((byte) 0xff);                                    // Hop limit
1892         packet.put(src.getAddress());                               // Source address
1893         packet.put(IPV6_ALL_NODES_ADDRESS);                         // Destination address
1894 
1895         packet.put((byte) ICMP6_ROUTER_ADVERTISEMENT);              // Type
1896         packet.put((byte) 0);                                       // Code (0)
1897         packet.putShort((short) 0);                                 // Checksum (ignored)
1898         packet.put((byte) 64);                                      // Hop limit
1899         packet.put((byte) 0);                                       // M/O, reserved
1900         packet.putShort((short) 1800);                              // Router lifetime
1901         packet.putInt(30_000);                                      // Reachable time
1902         packet.putInt(1000);                                        // Retrans timer
1903 
1904         addRioOption(packet, 1200, "64:ff9b::/96");
1905         addRdnssOption(packet, 7200, "2001:db8:1::1", "2001:db8:1::2");
1906         addRioOption(packet, 2100, "2000::/3");
1907         addRioOption(packet, 2400, "::/0");
1908         addPioOption(packet, 600, 300, "2001:db8:a::/64");
1909         addRioOption(packet, 1500, "2001:db8:c:d::/64");
1910         addPioOption(packet, 86400, 43200, "fd95:d1e:12::/64");
1911 
1912         int length = packet.position();
1913         packet.putShort(IPV6_PAYLOAD_LENGTH_OFFSET, (short) length);
1914 
1915         // Don't pass the Ra constructor a packet that is longer than the actual RA.
1916         // This relies on the fact that all the relative writes to the byte buffer are at the end.
1917         byte[] packetArray = new byte[length];
1918         packet.rewind();
1919         packet.get(packetArray);
1920         return packetArray;
1921     }
1922 
1923     @Test
testRaToString()1924     public void testRaToString() throws Exception {
1925         MockIpClientCallback cb = new MockIpClientCallback();
1926         ApfConfiguration config = getDefaultConfig();
1927         TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog);
1928 
1929         byte[] packet = buildLargeRa();
1930         ApfFilter.Ra ra = apfFilter.new Ra(packet, packet.length);
1931         String expected = "RA fe80::1234:abcd -> ff02::1 1800s "
1932                 + "2001:db8:a::/64 600s/300s fd95:d1e:12::/64 86400s/43200s "
1933                 + "DNS 7200s 2001:db8:1::1 2001:db8:1::2 "
1934                 + "RIO 1200s 64:ff9b::/96 RIO 2100s 2000::/3 "
1935                 + "RIO 2400s ::/0 RIO 1500s 2001:db8:c:d::/64 ";
1936         assertEquals(expected, ra.toString());
1937     }
1938 
1939     // Verify that the last program pushed to the IpClient.Callback properly filters the
1940     // given packet for the given lifetime.
verifyRaLifetime(byte[] program, ByteBuffer packet, int lifetime)1941     private void verifyRaLifetime(byte[] program, ByteBuffer packet, int lifetime) {
1942         final int FRACTION_OF_LIFETIME = 6;
1943         final int ageLimit = lifetime / FRACTION_OF_LIFETIME;
1944 
1945         // Verify new program should drop RA for 1/6th its lifetime and pass afterwards.
1946         assertDrop(program, packet.array());
1947         assertDrop(program, packet.array(), ageLimit);
1948         assertPass(program, packet.array(), ageLimit + 1);
1949         assertPass(program, packet.array(), lifetime);
1950         // Verify RA checksum is ignored
1951         final short originalChecksum = packet.getShort(ICMP6_RA_CHECKSUM_OFFSET);
1952         packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)12345);
1953         assertDrop(program, packet.array());
1954         packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)-12345);
1955         assertDrop(program, packet.array());
1956         packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, originalChecksum);
1957 
1958         // Verify other changes to RA (e.g., a change in the source address) make it not match.
1959         final int offset = IPV6_SRC_ADDR_OFFSET + 5;
1960         final byte originalByte = packet.get(offset);
1961         packet.put(offset, (byte) (~originalByte));
1962         assertPass(program, packet.array());
1963         packet.put(offset, originalByte);
1964         assertDrop(program, packet.array());
1965     }
1966 
1967     // Test that when ApfFilter is shown the given packet, it generates a program to filter it
1968     // for the given lifetime.
verifyRaLifetime(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback, ByteBuffer packet, int lifetime)1969     private void verifyRaLifetime(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback,
1970             ByteBuffer packet, int lifetime) throws IOException, ErrnoException {
1971         // Verify new program generated if ApfFilter witnesses RA
1972         ipClientCallback.resetApfProgramWait();
1973         apfFilter.pretendPacketReceived(packet.array());
1974         byte[] program = ipClientCallback.getApfProgram();
1975         verifyRaLifetime(program, packet, lifetime);
1976     }
1977 
verifyRaEvent(RaEvent expected)1978     private void verifyRaEvent(RaEvent expected) {
1979         ArgumentCaptor<IpConnectivityLog.Event> captor =
1980                 ArgumentCaptor.forClass(IpConnectivityLog.Event.class);
1981         verify(mLog, atLeastOnce()).log(captor.capture());
1982         RaEvent got = lastRaEvent(captor.getAllValues());
1983         if (!raEventEquals(expected, got)) {
1984             assertEquals(expected, got);  // fail for printing an assertion error message.
1985         }
1986     }
1987 
lastRaEvent(List<IpConnectivityLog.Event> events)1988     private RaEvent lastRaEvent(List<IpConnectivityLog.Event> events) {
1989         RaEvent got = null;
1990         for (Parcelable ev : events) {
1991             if (ev instanceof RaEvent) {
1992                 got = (RaEvent) ev;
1993             }
1994         }
1995         return got;
1996     }
1997 
raEventEquals(RaEvent ev1, RaEvent ev2)1998     private boolean raEventEquals(RaEvent ev1, RaEvent ev2) {
1999         return (ev1 != null) && (ev2 != null)
2000                 && (ev1.routerLifetime == ev2.routerLifetime)
2001                 && (ev1.prefixValidLifetime == ev2.prefixValidLifetime)
2002                 && (ev1.prefixPreferredLifetime == ev2.prefixPreferredLifetime)
2003                 && (ev1.routeInfoLifetime == ev2.routeInfoLifetime)
2004                 && (ev1.rdnssLifetime == ev2.rdnssLifetime)
2005                 && (ev1.dnsslLifetime == ev2.dnsslLifetime);
2006     }
2007 
assertInvalidRa(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback, ByteBuffer packet)2008     private void assertInvalidRa(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback,
2009             ByteBuffer packet) throws IOException, ErrnoException {
2010         ipClientCallback.resetApfProgramWait();
2011         apfFilter.pretendPacketReceived(packet.array());
2012         ipClientCallback.assertNoProgramUpdate();
2013     }
2014 
makeBaseRaPacket()2015     private ByteBuffer makeBaseRaPacket() {
2016         ByteBuffer basePacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]);
2017         final int ROUTER_LIFETIME = 1000;
2018         final int VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET = ETH_HEADER_LEN;
2019         // IPv6, traffic class = 0, flow label = 0x12345
2020         final int VERSION_TRAFFIC_CLASS_FLOW_LABEL = 0x60012345;
2021 
2022         basePacket.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IPV6);
2023         basePacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET,
2024                 VERSION_TRAFFIC_CLASS_FLOW_LABEL);
2025         basePacket.put(IPV6_NEXT_HEADER_OFFSET, (byte) IPPROTO_ICMPV6);
2026         basePacket.put(ICMP6_TYPE_OFFSET, (byte) ICMP6_ROUTER_ADVERTISEMENT);
2027         basePacket.putShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET, (short) ROUTER_LIFETIME);
2028         basePacket.position(IPV6_DEST_ADDR_OFFSET);
2029         basePacket.put(IPV6_ALL_NODES_ADDRESS);
2030 
2031         return basePacket;
2032     }
2033 
2034     @Test
testApfFilterRa()2035     public void testApfFilterRa() throws Exception {
2036         MockIpClientCallback ipClientCallback = new MockIpClientCallback();
2037         ApfConfiguration config = getDefaultConfig();
2038         config.multicastFilter = DROP_MULTICAST;
2039         config.ieee802_3Filter = DROP_802_3_FRAMES;
2040         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
2041         byte[] program = ipClientCallback.getApfProgram();
2042 
2043         final int ROUTER_LIFETIME = 1000;
2044         final int PREFIX_VALID_LIFETIME = 200;
2045         final int PREFIX_PREFERRED_LIFETIME = 100;
2046         final int RDNSS_LIFETIME  = 300;
2047         final int ROUTE_LIFETIME  = 400;
2048         // Note that lifetime of 2000 will be ignored in favor of shorter route lifetime of 1000.
2049         final int DNSSL_LIFETIME  = 2000;
2050         final int VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET = ETH_HEADER_LEN;
2051         // IPv6, traffic class = 0, flow label = 0x12345
2052         final int VERSION_TRAFFIC_CLASS_FLOW_LABEL = 0x60012345;
2053 
2054         // Verify RA is passed the first time
2055         ByteBuffer basePacket = makeBaseRaPacket();
2056         assertPass(program, basePacket.array());
2057 
2058         verifyRaLifetime(apfFilter, ipClientCallback, basePacket, ROUTER_LIFETIME);
2059         verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, -1));
2060 
2061         ByteBuffer newFlowLabelPacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]);
2062         basePacket.clear();
2063         newFlowLabelPacket.put(basePacket);
2064         // Check that changes are ignored in every byte of the flow label.
2065         newFlowLabelPacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET,
2066                 VERSION_TRAFFIC_CLASS_FLOW_LABEL + 0x11111);
2067 
2068         // Ensure zero-length options cause the packet to be silently skipped.
2069         // Do this before we test other packets. http://b/29586253
2070         ByteBuffer zeroLengthOptionPacket = ByteBuffer.wrap(
2071                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
2072         basePacket.clear();
2073         zeroLengthOptionPacket.put(basePacket);
2074         zeroLengthOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE);
2075         zeroLengthOptionPacket.put((byte)0);
2076         assertInvalidRa(apfFilter, ipClientCallback, zeroLengthOptionPacket);
2077 
2078         // Generate several RAs with different options and lifetimes, and verify when
2079         // ApfFilter is shown these packets, it generates programs to filter them for the
2080         // appropriate lifetime.
2081         ByteBuffer prefixOptionPacket = ByteBuffer.wrap(
2082                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_LEN]);
2083         basePacket.clear();
2084         prefixOptionPacket.put(basePacket);
2085         addPioOption(prefixOptionPacket, PREFIX_VALID_LIFETIME, PREFIX_PREFERRED_LIFETIME,
2086                 "2001:db8::/64");
2087         verifyRaLifetime(
2088                 apfFilter, ipClientCallback, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
2089         verifyRaEvent(new RaEvent(
2090                 ROUTER_LIFETIME, PREFIX_VALID_LIFETIME, PREFIX_PREFERRED_LIFETIME, -1, -1, -1));
2091 
2092         ByteBuffer rdnssOptionPacket = ByteBuffer.wrap(
2093                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN + 2 * IPV6_ADDR_LEN]);
2094         basePacket.clear();
2095         rdnssOptionPacket.put(basePacket);
2096         addRdnssOption(rdnssOptionPacket, RDNSS_LIFETIME,
2097                 "2001:4860:4860::8888", "2001:4860:4860::8844");
2098         verifyRaLifetime(apfFilter, ipClientCallback, rdnssOptionPacket, RDNSS_LIFETIME);
2099         verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, RDNSS_LIFETIME, -1));
2100 
2101         final int lowLifetime = 60;
2102         ByteBuffer lowLifetimeRdnssOptionPacket = ByteBuffer.wrap(
2103                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN + IPV6_ADDR_LEN]);
2104         basePacket.clear();
2105         lowLifetimeRdnssOptionPacket.put(basePacket);
2106         addRdnssOption(lowLifetimeRdnssOptionPacket, lowLifetime, "2620:fe::9");
2107         verifyRaLifetime(apfFilter, ipClientCallback, lowLifetimeRdnssOptionPacket,
2108                 ROUTER_LIFETIME);
2109         verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, lowLifetime, -1));
2110 
2111         ByteBuffer routeInfoOptionPacket = ByteBuffer.wrap(
2112                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN + IPV6_ADDR_LEN]);
2113         basePacket.clear();
2114         routeInfoOptionPacket.put(basePacket);
2115         addRioOption(routeInfoOptionPacket, ROUTE_LIFETIME, "64:ff9b::/96");
2116         verifyRaLifetime(apfFilter, ipClientCallback, routeInfoOptionPacket, ROUTE_LIFETIME);
2117         verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, ROUTE_LIFETIME, -1, -1));
2118 
2119         // Check that RIOs differing only in the first 4 bytes are different.
2120         ByteBuffer similarRouteInfoOptionPacket = ByteBuffer.wrap(
2121                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN + IPV6_ADDR_LEN]);
2122         basePacket.clear();
2123         similarRouteInfoOptionPacket.put(basePacket);
2124         addRioOption(similarRouteInfoOptionPacket, ROUTE_LIFETIME, "64:ff9b::/64");
2125         // Packet should be passed because it is different.
2126         program = ipClientCallback.getApfProgram();
2127         assertPass(program, similarRouteInfoOptionPacket.array());
2128 
2129         ByteBuffer dnsslOptionPacket = ByteBuffer.wrap(
2130                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
2131         basePacket.clear();
2132         dnsslOptionPacket.put(basePacket);
2133         dnsslOptionPacket.put((byte)ICMP6_DNSSL_OPTION_TYPE);
2134         dnsslOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
2135         dnsslOptionPacket.putInt(
2136                 ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, DNSSL_LIFETIME);
2137         verifyRaLifetime(apfFilter, ipClientCallback, dnsslOptionPacket, ROUTER_LIFETIME);
2138         verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, DNSSL_LIFETIME));
2139 
2140         ByteBuffer largeRaPacket = ByteBuffer.wrap(buildLargeRa());
2141         verifyRaLifetime(apfFilter, ipClientCallback, largeRaPacket, 300);
2142         verifyRaEvent(new RaEvent(1800, 600, 300, 1200, 7200, -1));
2143 
2144         // Verify that current program filters all the RAs (note: ApfFilter.MAX_RAS == 10).
2145         program = ipClientCallback.getApfProgram();
2146         verifyRaLifetime(program, basePacket, ROUTER_LIFETIME);
2147         verifyRaLifetime(program, newFlowLabelPacket, ROUTER_LIFETIME);
2148         verifyRaLifetime(program, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
2149         verifyRaLifetime(program, rdnssOptionPacket, RDNSS_LIFETIME);
2150         verifyRaLifetime(program, lowLifetimeRdnssOptionPacket, ROUTER_LIFETIME);
2151         verifyRaLifetime(program, routeInfoOptionPacket, ROUTE_LIFETIME);
2152         verifyRaLifetime(program, dnsslOptionPacket, ROUTER_LIFETIME);
2153         verifyRaLifetime(program, largeRaPacket, 300);
2154 
2155         apfFilter.shutdown();
2156     }
2157 
2158     @Test
testRaWithDifferentReachableTimeAndRetransTimer()2159     public void testRaWithDifferentReachableTimeAndRetransTimer() throws Exception {
2160         final MockIpClientCallback ipClientCallback = new MockIpClientCallback();
2161         final ApfConfiguration config = getDefaultConfig();
2162         config.multicastFilter = DROP_MULTICAST;
2163         config.ieee802_3Filter = DROP_802_3_FRAMES;
2164         final TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
2165         byte[] program = ipClientCallback.getApfProgram();
2166         final int RA_REACHABLE_TIME = 1800;
2167         final int RA_RETRANSMISSION_TIMER = 1234;
2168 
2169         // Create an Ra packet without options
2170         // Reachable time = 1800, retransmission timer = 1234
2171         ByteBuffer raPacket = makeBaseRaPacket();
2172         raPacket.position(ICMP6_RA_REACHABLE_TIME_OFFSET);
2173         raPacket.putInt(RA_REACHABLE_TIME);
2174         raPacket.putInt(RA_RETRANSMISSION_TIMER);
2175         // First RA passes filter
2176         assertPass(program, raPacket.array());
2177 
2178         // Assume apf is shown the given RA, it generates program to filter it.
2179         ipClientCallback.resetApfProgramWait();
2180         apfFilter.pretendPacketReceived(raPacket.array());
2181         program = ipClientCallback.getApfProgram();
2182         assertDrop(program, raPacket.array());
2183 
2184         // A packet with different reachable time should be passed.
2185         // Reachable time = 2300, retransmission timer = 1234
2186         raPacket.clear();
2187         raPacket.putInt(ICMP6_RA_REACHABLE_TIME_OFFSET, RA_REACHABLE_TIME + 500);
2188         assertPass(program, raPacket.array());
2189 
2190         // A packet with different retransmission timer should be passed.
2191         // Reachable time = 1800, retransmission timer = 2234
2192         raPacket.clear();
2193         raPacket.putInt(ICMP6_RA_REACHABLE_TIME_OFFSET, RA_REACHABLE_TIME);
2194         raPacket.putInt(ICMP6_RA_RETRANSMISSION_TIMER_OFFSET, RA_RETRANSMISSION_TIMER + 1000);
2195         assertPass(program, raPacket.array());
2196     }
2197 
2198     /**
2199      * Stage a file for testing, i.e. make it native accessible. Given a resource ID,
2200      * copy that resource into the app's data directory and return the path to it.
2201      */
stageFile(int rawId)2202     private String stageFile(int rawId) throws Exception {
2203         File file = new File(InstrumentationRegistry.getContext().getFilesDir(), "staged_file");
2204         new File(file.getParent()).mkdirs();
2205         InputStream in = null;
2206         OutputStream out = null;
2207         try {
2208             in = InstrumentationRegistry.getContext().getResources().openRawResource(rawId);
2209             out = new FileOutputStream(file);
2210             Streams.copy(in, out);
2211         } finally {
2212             if (in != null) in.close();
2213             if (out != null) out.close();
2214         }
2215         return file.getAbsolutePath();
2216     }
2217 
put(ByteBuffer buffer, int position, byte[] bytes)2218     private static void put(ByteBuffer buffer, int position, byte[] bytes) {
2219         final int original = buffer.position();
2220         buffer.position(position);
2221         buffer.put(bytes);
2222         buffer.position(original);
2223     }
2224 
2225     @Test
testRaParsing()2226     public void testRaParsing() throws Exception {
2227         final int maxRandomPacketSize = 512;
2228         final Random r = new Random();
2229         MockIpClientCallback cb = new MockIpClientCallback();
2230         ApfConfiguration config = getDefaultConfig();
2231         config.multicastFilter = DROP_MULTICAST;
2232         config.ieee802_3Filter = DROP_802_3_FRAMES;
2233         TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog);
2234         for (int i = 0; i < 1000; i++) {
2235             byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
2236             r.nextBytes(packet);
2237             try {
2238                 apfFilter.new Ra(packet, packet.length);
2239             } catch (ApfFilter.InvalidRaException e) {
2240             } catch (Exception e) {
2241                 throw new Exception("bad packet: " + HexDump.toHexString(packet), e);
2242             }
2243         }
2244     }
2245 
2246     @Test
testRaProcessing()2247     public void testRaProcessing() throws Exception {
2248         final int maxRandomPacketSize = 512;
2249         final Random r = new Random();
2250         MockIpClientCallback cb = new MockIpClientCallback();
2251         ApfConfiguration config = getDefaultConfig();
2252         config.multicastFilter = DROP_MULTICAST;
2253         config.ieee802_3Filter = DROP_802_3_FRAMES;
2254         TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog);
2255         for (int i = 0; i < 1000; i++) {
2256             byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
2257             r.nextBytes(packet);
2258             try {
2259                 apfFilter.processRa(packet, packet.length);
2260             } catch (Exception e) {
2261                 throw new Exception("bad packet: " + HexDump.toHexString(packet), e);
2262             }
2263         }
2264     }
2265 
2266     /**
2267      * Call the APF interpreter to run {@code program} on {@code packet} with persistent memory
2268      * segment {@data} pretending the filter was installed {@code filter_age} seconds ago.
2269      */
apfSimulate(byte[] program, byte[] packet, byte[] data, int filter_age)2270     private native static int apfSimulate(byte[] program, byte[] packet, byte[] data,
2271         int filter_age);
2272 
2273     /**
2274      * Compile a tcpdump human-readable filter (e.g. "icmp" or "tcp port 54") into a BPF
2275      * prorgam and return a human-readable dump of the BPF program identical to "tcpdump -d".
2276      */
compileToBpf(String filter)2277     private native static String compileToBpf(String filter);
2278 
2279     /**
2280      * Open packet capture file {@code pcap_filename} and filter the packets using tcpdump
2281      * human-readable filter (e.g. "icmp" or "tcp port 54") compiled to a BPF program and
2282      * at the same time using APF program {@code apf_program}.  Return {@code true} if
2283      * both APF and BPF programs filter out exactly the same packets.
2284      */
compareBpfApf(String filter, String pcap_filename, byte[] apf_program)2285     private native static boolean compareBpfApf(String filter, String pcap_filename,
2286             byte[] apf_program);
2287 
2288 
2289     /**
2290      * Open packet capture file {@code pcapFilename} and run it through APF filter. Then
2291      * checks whether all the packets are dropped and populates data[] {@code data} with
2292      * the APF counters.
2293      */
dropsAllPackets(byte[] program, byte[] data, String pcapFilename)2294     private native static boolean dropsAllPackets(byte[] program, byte[] data, String pcapFilename);
2295 
2296     @Test
testBroadcastAddress()2297     public void testBroadcastAddress() throws Exception {
2298         assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 0));
2299         assertEqualsIp("0.0.0.0", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 32));
2300         assertEqualsIp("0.0.3.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 22));
2301         assertEqualsIp("0.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 8));
2302 
2303         assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 0));
2304         assertEqualsIp("10.0.0.1", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 32));
2305         assertEqualsIp("10.0.0.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 24));
2306         assertEqualsIp("10.0.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 16));
2307     }
2308 
assertEqualsIp(String expected, int got)2309     public void assertEqualsIp(String expected, int got) throws Exception {
2310         int want = Inet4AddressUtils.inet4AddressToIntHTH(
2311                 (Inet4Address) InetAddresses.parseNumericAddress(expected));
2312         assertEquals(want, got);
2313     }
2314 }
2315