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