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