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