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