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