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