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