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