1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.net.apf; 18 19 import static android.net.util.NetworkConstants.*; 20 import static android.system.OsConstants.*; 21 import static com.android.internal.util.BitUtils.bytesToBEInt; 22 import static com.android.internal.util.BitUtils.put; 23 import static org.junit.Assert.assertEquals; 24 import static org.junit.Assert.assertFalse; 25 import static org.junit.Assert.assertTrue; 26 import static org.junit.Assert.fail; 27 import static org.mockito.Mockito.atLeastOnce; 28 import static org.mockito.Mockito.verify; 29 30 import android.content.Context; 31 import android.net.LinkAddress; 32 import android.net.LinkProperties; 33 import android.net.apf.ApfFilter.ApfConfiguration; 34 import android.net.apf.ApfGenerator.IllegalInstructionException; 35 import android.net.apf.ApfGenerator.Register; 36 import android.net.ip.IpClient; 37 import android.net.metrics.IpConnectivityLog; 38 import android.net.metrics.RaEvent; 39 import android.net.util.InterfaceParams; 40 import android.os.ConditionVariable; 41 import android.os.Parcelable; 42 import android.os.SystemClock; 43 import android.support.test.InstrumentationRegistry; 44 import android.support.test.filters.SmallTest; 45 import android.support.test.runner.AndroidJUnit4; 46 import android.system.ErrnoException; 47 import android.system.Os; 48 import android.text.format.DateUtils; 49 import com.android.frameworks.tests.net.R; 50 import com.android.internal.util.HexDump; 51 import java.io.File; 52 import java.io.FileDescriptor; 53 import java.io.FileOutputStream; 54 import java.io.IOException; 55 import java.io.InputStream; 56 import java.io.OutputStream; 57 import java.net.InetAddress; 58 import java.nio.ByteBuffer; 59 import java.util.List; 60 import java.util.Random; 61 import libcore.io.IoUtils; 62 import libcore.io.Streams; 63 import org.junit.Before; 64 import org.junit.Test; 65 import org.junit.runner.RunWith; 66 import org.mockito.ArgumentCaptor; 67 import org.mockito.Mock; 68 import org.mockito.MockitoAnnotations; 69 70 /** 71 * Tests for APF program generator and interpreter. 72 * 73 * Build, install and run with: 74 * runtest frameworks-net -c android.net.apf.ApfTest 75 */ 76 @RunWith(AndroidJUnit4.class) 77 @SmallTest 78 public class ApfTest { 79 private static final int TIMEOUT_MS = 500; 80 private final static int MIN_APF_VERSION = 2; 81 82 @Mock IpConnectivityLog mLog; 83 @Mock Context mContext; 84 85 @Before 86 public void setUp() throws Exception { 87 MockitoAnnotations.initMocks(this); 88 // Load up native shared library containing APF interpreter exposed via JNI. 89 System.loadLibrary("frameworksnettestsjni"); 90 } 91 92 // Expected return codes from APF interpreter. 93 private final static int PASS = 1; 94 private final static int DROP = 0; 95 // Interpreter will just accept packets without link layer headers, so pad fake packet to at 96 // least the minimum packet size. 97 private final static int MIN_PKT_SIZE = 15; 98 99 private static final ApfCapabilities MOCK_APF_CAPABILITIES = 100 new ApfCapabilities(2, 1700, ARPHRD_ETHER); 101 102 private final static boolean DROP_MULTICAST = true; 103 private final static boolean ALLOW_MULTICAST = false; 104 105 private final static boolean DROP_802_3_FRAMES = true; 106 private final static boolean ALLOW_802_3_FRAMES = false; 107 108 private static ApfConfiguration getDefaultConfig() { 109 ApfFilter.ApfConfiguration config = new ApfConfiguration(); 110 config.apfCapabilities = MOCK_APF_CAPABILITIES; 111 config.multicastFilter = ALLOW_MULTICAST; 112 config.ieee802_3Filter = ALLOW_802_3_FRAMES; 113 config.ethTypeBlackList = new int[0]; 114 return config; 115 } 116 117 private static String label(int code) { 118 switch (code) { 119 case PASS: return "PASS"; 120 case DROP: return "DROP"; 121 default: return "UNKNOWN"; 122 } 123 } 124 125 private static void assertReturnCodesEqual(int expected, int got) { 126 assertEquals(label(expected), label(got)); 127 } 128 129 private void assertVerdict(int expected, byte[] program, byte[] packet, int filterAge) { 130 assertReturnCodesEqual(expected, apfSimulate(program, packet, null, filterAge)); 131 } 132 133 private void assertVerdict(int expected, byte[] program, byte[] packet) { 134 assertReturnCodesEqual(expected, apfSimulate(program, packet, null, 0)); 135 } 136 137 private void assertPass(byte[] program, byte[] packet, int filterAge) { 138 assertVerdict(PASS, program, packet, filterAge); 139 } 140 141 private void assertPass(byte[] program, byte[] packet) { 142 assertVerdict(PASS, program, packet); 143 } 144 145 private void assertDrop(byte[] program, byte[] packet, int filterAge) { 146 assertVerdict(DROP, program, packet, filterAge); 147 } 148 149 private void assertDrop(byte[] program, byte[] packet) { 150 assertVerdict(DROP, program, packet); 151 } 152 153 private void assertProgramEquals(byte[] expected, byte[] program) throws AssertionError { 154 // assertArrayEquals() would only print one byte, making debugging difficult. 155 if (!java.util.Arrays.equals(expected, program)) { 156 throw new AssertionError( 157 "\nexpected: " + HexDump.toHexString(expected) + 158 "\nactual: " + HexDump.toHexString(program)); 159 } 160 } 161 162 private void assertDataMemoryContents( 163 int expected, byte[] program, byte[] packet, byte[] data, byte[] expected_data) 164 throws IllegalInstructionException, Exception { 165 assertReturnCodesEqual(expected, apfSimulate(program, packet, data, 0 /* filterAge */)); 166 167 // assertArrayEquals() would only print one byte, making debugging difficult. 168 if (!java.util.Arrays.equals(expected_data, data)) { 169 throw new Exception( 170 "\nprogram: " + HexDump.toHexString(program) + 171 "\ndata memory: " + HexDump.toHexString(data) + 172 "\nexpected: " + HexDump.toHexString(expected_data)); 173 } 174 } 175 176 private void assertVerdict(int expected, ApfGenerator gen, byte[] packet, int filterAge) 177 throws IllegalInstructionException { 178 assertReturnCodesEqual(expected, apfSimulate(gen.generate(), packet, null, 179 filterAge)); 180 } 181 182 private void assertPass(ApfGenerator gen, byte[] packet, int filterAge) 183 throws IllegalInstructionException { 184 assertVerdict(PASS, gen, packet, filterAge); 185 } 186 187 private void assertDrop(ApfGenerator gen, byte[] packet, int filterAge) 188 throws IllegalInstructionException { 189 assertVerdict(DROP, gen, packet, filterAge); 190 } 191 192 private void assertPass(ApfGenerator gen) 193 throws IllegalInstructionException { 194 assertVerdict(PASS, gen, new byte[MIN_PKT_SIZE], 0); 195 } 196 197 private void assertDrop(ApfGenerator gen) 198 throws IllegalInstructionException { 199 assertVerdict(DROP, gen, new byte[MIN_PKT_SIZE], 0); 200 } 201 202 /** 203 * Test each instruction by generating a program containing the instruction, 204 * generating bytecode for that program and running it through the 205 * interpreter to verify it functions correctly. 206 */ 207 @Test 208 public void testApfInstructions() throws IllegalInstructionException { 209 // Empty program should pass because having the program counter reach the 210 // location immediately after the program indicates the packet should be 211 // passed to the AP. 212 ApfGenerator gen = new ApfGenerator(MIN_APF_VERSION); 213 assertPass(gen); 214 215 // Test jumping to pass label. 216 gen = new ApfGenerator(MIN_APF_VERSION); 217 gen.addJump(gen.PASS_LABEL); 218 byte[] program = gen.generate(); 219 assertEquals(1, program.length); 220 assertEquals((14 << 3) | (0 << 1) | 0, program[0]); 221 assertPass(program, new byte[MIN_PKT_SIZE], 0); 222 223 // Test jumping to drop label. 224 gen = new ApfGenerator(MIN_APF_VERSION); 225 gen.addJump(gen.DROP_LABEL); 226 program = gen.generate(); 227 assertEquals(2, program.length); 228 assertEquals((14 << 3) | (1 << 1) | 0, program[0]); 229 assertEquals(1, program[1]); 230 assertDrop(program, new byte[15], 15); 231 232 // Test jumping if equal to 0. 233 gen = new ApfGenerator(MIN_APF_VERSION); 234 gen.addJumpIfR0Equals(0, gen.DROP_LABEL); 235 assertDrop(gen); 236 237 // Test jumping if not equal to 0. 238 gen = new ApfGenerator(MIN_APF_VERSION); 239 gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL); 240 assertPass(gen); 241 gen = new ApfGenerator(MIN_APF_VERSION); 242 gen.addLoadImmediate(Register.R0, 1); 243 gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL); 244 assertDrop(gen); 245 246 // Test jumping if registers equal. 247 gen = new ApfGenerator(MIN_APF_VERSION); 248 gen.addJumpIfR0EqualsR1(gen.DROP_LABEL); 249 assertDrop(gen); 250 251 // Test jumping if registers not equal. 252 gen = new ApfGenerator(MIN_APF_VERSION); 253 gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL); 254 assertPass(gen); 255 gen = new ApfGenerator(MIN_APF_VERSION); 256 gen.addLoadImmediate(Register.R0, 1); 257 gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL); 258 assertDrop(gen); 259 260 // Test load immediate. 261 gen = new ApfGenerator(MIN_APF_VERSION); 262 gen.addLoadImmediate(Register.R0, 1234567890); 263 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL); 264 assertDrop(gen); 265 266 // Test add. 267 gen = new ApfGenerator(MIN_APF_VERSION); 268 gen.addAdd(1234567890); 269 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL); 270 assertDrop(gen); 271 272 // Test subtract. 273 gen = new ApfGenerator(MIN_APF_VERSION); 274 gen.addAdd(-1234567890); 275 gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL); 276 assertDrop(gen); 277 278 // Test or. 279 gen = new ApfGenerator(MIN_APF_VERSION); 280 gen.addOr(1234567890); 281 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL); 282 assertDrop(gen); 283 284 // Test and. 285 gen = new ApfGenerator(MIN_APF_VERSION); 286 gen.addLoadImmediate(Register.R0, 1234567890); 287 gen.addAnd(123456789); 288 gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL); 289 assertDrop(gen); 290 291 // Test left shift. 292 gen = new ApfGenerator(MIN_APF_VERSION); 293 gen.addLoadImmediate(Register.R0, 1234567890); 294 gen.addLeftShift(1); 295 gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL); 296 assertDrop(gen); 297 298 // Test right shift. 299 gen = new ApfGenerator(MIN_APF_VERSION); 300 gen.addLoadImmediate(Register.R0, 1234567890); 301 gen.addRightShift(1); 302 gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL); 303 assertDrop(gen); 304 305 // Test multiply. 306 gen = new ApfGenerator(MIN_APF_VERSION); 307 gen.addLoadImmediate(Register.R0, 1234567890); 308 gen.addMul(2); 309 gen.addJumpIfR0Equals(1234567890 * 2, gen.DROP_LABEL); 310 assertDrop(gen); 311 312 // Test divide. 313 gen = new ApfGenerator(MIN_APF_VERSION); 314 gen.addLoadImmediate(Register.R0, 1234567890); 315 gen.addDiv(2); 316 gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL); 317 assertDrop(gen); 318 319 // Test divide by zero. 320 gen = new ApfGenerator(MIN_APF_VERSION); 321 gen.addDiv(0); 322 gen.addJump(gen.DROP_LABEL); 323 assertPass(gen); 324 325 // Test add. 326 gen = new ApfGenerator(MIN_APF_VERSION); 327 gen.addLoadImmediate(Register.R1, 1234567890); 328 gen.addAddR1(); 329 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL); 330 assertDrop(gen); 331 332 // Test subtract. 333 gen = new ApfGenerator(MIN_APF_VERSION); 334 gen.addLoadImmediate(Register.R1, -1234567890); 335 gen.addAddR1(); 336 gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL); 337 assertDrop(gen); 338 339 // Test or. 340 gen = new ApfGenerator(MIN_APF_VERSION); 341 gen.addLoadImmediate(Register.R1, 1234567890); 342 gen.addOrR1(); 343 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL); 344 assertDrop(gen); 345 346 // Test and. 347 gen = new ApfGenerator(MIN_APF_VERSION); 348 gen.addLoadImmediate(Register.R0, 1234567890); 349 gen.addLoadImmediate(Register.R1, 123456789); 350 gen.addAndR1(); 351 gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL); 352 assertDrop(gen); 353 354 // Test left shift. 355 gen = new ApfGenerator(MIN_APF_VERSION); 356 gen.addLoadImmediate(Register.R0, 1234567890); 357 gen.addLoadImmediate(Register.R1, 1); 358 gen.addLeftShiftR1(); 359 gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL); 360 assertDrop(gen); 361 362 // Test right shift. 363 gen = new ApfGenerator(MIN_APF_VERSION); 364 gen.addLoadImmediate(Register.R0, 1234567890); 365 gen.addLoadImmediate(Register.R1, -1); 366 gen.addLeftShiftR1(); 367 gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL); 368 assertDrop(gen); 369 370 // Test multiply. 371 gen = new ApfGenerator(MIN_APF_VERSION); 372 gen.addLoadImmediate(Register.R0, 1234567890); 373 gen.addLoadImmediate(Register.R1, 2); 374 gen.addMulR1(); 375 gen.addJumpIfR0Equals(1234567890 * 2, gen.DROP_LABEL); 376 assertDrop(gen); 377 378 // Test divide. 379 gen = new ApfGenerator(MIN_APF_VERSION); 380 gen.addLoadImmediate(Register.R0, 1234567890); 381 gen.addLoadImmediate(Register.R1, 2); 382 gen.addDivR1(); 383 gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL); 384 assertDrop(gen); 385 386 // Test divide by zero. 387 gen = new ApfGenerator(MIN_APF_VERSION); 388 gen.addDivR1(); 389 gen.addJump(gen.DROP_LABEL); 390 assertPass(gen); 391 392 // Test byte load. 393 gen = new ApfGenerator(MIN_APF_VERSION); 394 gen.addLoad8(Register.R0, 1); 395 gen.addJumpIfR0Equals(45, gen.DROP_LABEL); 396 assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0); 397 398 // Test out of bounds load. 399 gen = new ApfGenerator(MIN_APF_VERSION); 400 gen.addLoad8(Register.R0, 16); 401 gen.addJumpIfR0Equals(0, gen.DROP_LABEL); 402 assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0); 403 404 // Test half-word load. 405 gen = new ApfGenerator(MIN_APF_VERSION); 406 gen.addLoad16(Register.R0, 1); 407 gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL); 408 assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0); 409 410 // Test word load. 411 gen = new ApfGenerator(MIN_APF_VERSION); 412 gen.addLoad32(Register.R0, 1); 413 gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL); 414 assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0); 415 416 // Test byte indexed load. 417 gen = new ApfGenerator(MIN_APF_VERSION); 418 gen.addLoadImmediate(Register.R1, 1); 419 gen.addLoad8Indexed(Register.R0, 0); 420 gen.addJumpIfR0Equals(45, gen.DROP_LABEL); 421 assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0); 422 423 // Test out of bounds indexed load. 424 gen = new ApfGenerator(MIN_APF_VERSION); 425 gen.addLoadImmediate(Register.R1, 8); 426 gen.addLoad8Indexed(Register.R0, 8); 427 gen.addJumpIfR0Equals(0, gen.DROP_LABEL); 428 assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0); 429 430 // Test half-word indexed load. 431 gen = new ApfGenerator(MIN_APF_VERSION); 432 gen.addLoadImmediate(Register.R1, 1); 433 gen.addLoad16Indexed(Register.R0, 0); 434 gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL); 435 assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0); 436 437 // Test word indexed load. 438 gen = new ApfGenerator(MIN_APF_VERSION); 439 gen.addLoadImmediate(Register.R1, 1); 440 gen.addLoad32Indexed(Register.R0, 0); 441 gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL); 442 assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0); 443 444 // Test jumping if greater than. 445 gen = new ApfGenerator(MIN_APF_VERSION); 446 gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL); 447 assertPass(gen); 448 gen = new ApfGenerator(MIN_APF_VERSION); 449 gen.addLoadImmediate(Register.R0, 1); 450 gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL); 451 assertDrop(gen); 452 453 // Test jumping if less than. 454 gen = new ApfGenerator(MIN_APF_VERSION); 455 gen.addJumpIfR0LessThan(0, gen.DROP_LABEL); 456 assertPass(gen); 457 gen = new ApfGenerator(MIN_APF_VERSION); 458 gen.addJumpIfR0LessThan(1, gen.DROP_LABEL); 459 assertDrop(gen); 460 461 // Test jumping if any bits set. 462 gen = new ApfGenerator(MIN_APF_VERSION); 463 gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL); 464 assertPass(gen); 465 gen = new ApfGenerator(MIN_APF_VERSION); 466 gen.addLoadImmediate(Register.R0, 1); 467 gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL); 468 assertDrop(gen); 469 gen = new ApfGenerator(MIN_APF_VERSION); 470 gen.addLoadImmediate(Register.R0, 3); 471 gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL); 472 assertDrop(gen); 473 474 // Test jumping if register greater than. 475 gen = new ApfGenerator(MIN_APF_VERSION); 476 gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL); 477 assertPass(gen); 478 gen = new ApfGenerator(MIN_APF_VERSION); 479 gen.addLoadImmediate(Register.R0, 2); 480 gen.addLoadImmediate(Register.R1, 1); 481 gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL); 482 assertDrop(gen); 483 484 // Test jumping if register less than. 485 gen = new ApfGenerator(MIN_APF_VERSION); 486 gen.addJumpIfR0LessThanR1(gen.DROP_LABEL); 487 assertPass(gen); 488 gen = new ApfGenerator(MIN_APF_VERSION); 489 gen.addLoadImmediate(Register.R1, 1); 490 gen.addJumpIfR0LessThanR1(gen.DROP_LABEL); 491 assertDrop(gen); 492 493 // Test jumping if any bits set in register. 494 gen = new ApfGenerator(MIN_APF_VERSION); 495 gen.addLoadImmediate(Register.R1, 3); 496 gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL); 497 assertPass(gen); 498 gen = new ApfGenerator(MIN_APF_VERSION); 499 gen.addLoadImmediate(Register.R1, 3); 500 gen.addLoadImmediate(Register.R0, 1); 501 gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL); 502 assertDrop(gen); 503 gen = new ApfGenerator(MIN_APF_VERSION); 504 gen.addLoadImmediate(Register.R1, 3); 505 gen.addLoadImmediate(Register.R0, 3); 506 gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL); 507 assertDrop(gen); 508 509 // Test load from memory. 510 gen = new ApfGenerator(MIN_APF_VERSION); 511 gen.addLoadFromMemory(Register.R0, 0); 512 gen.addJumpIfR0Equals(0, gen.DROP_LABEL); 513 assertDrop(gen); 514 515 // Test store to memory. 516 gen = new ApfGenerator(MIN_APF_VERSION); 517 gen.addLoadImmediate(Register.R1, 1234567890); 518 gen.addStoreToMemory(Register.R1, 12); 519 gen.addLoadFromMemory(Register.R0, 12); 520 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL); 521 assertDrop(gen); 522 523 // Test filter age pre-filled memory. 524 gen = new ApfGenerator(MIN_APF_VERSION); 525 gen.addLoadFromMemory(Register.R0, gen.FILTER_AGE_MEMORY_SLOT); 526 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL); 527 assertDrop(gen, new byte[MIN_PKT_SIZE], 1234567890); 528 529 // Test packet size pre-filled memory. 530 gen = new ApfGenerator(MIN_APF_VERSION); 531 gen.addLoadFromMemory(Register.R0, gen.PACKET_SIZE_MEMORY_SLOT); 532 gen.addJumpIfR0Equals(MIN_PKT_SIZE, gen.DROP_LABEL); 533 assertDrop(gen); 534 535 // Test IPv4 header size pre-filled memory. 536 gen = new ApfGenerator(MIN_APF_VERSION); 537 gen.addLoadFromMemory(Register.R0, gen.IPV4_HEADER_SIZE_MEMORY_SLOT); 538 gen.addJumpIfR0Equals(20, gen.DROP_LABEL); 539 assertDrop(gen, new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x45}, 0); 540 541 // Test not. 542 gen = new ApfGenerator(MIN_APF_VERSION); 543 gen.addLoadImmediate(Register.R0, 1234567890); 544 gen.addNot(Register.R0); 545 gen.addJumpIfR0Equals(~1234567890, gen.DROP_LABEL); 546 assertDrop(gen); 547 548 // Test negate. 549 gen = new ApfGenerator(MIN_APF_VERSION); 550 gen.addLoadImmediate(Register.R0, 1234567890); 551 gen.addNeg(Register.R0); 552 gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL); 553 assertDrop(gen); 554 555 // Test move. 556 gen = new ApfGenerator(MIN_APF_VERSION); 557 gen.addLoadImmediate(Register.R1, 1234567890); 558 gen.addMove(Register.R0); 559 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL); 560 assertDrop(gen); 561 gen = new ApfGenerator(MIN_APF_VERSION); 562 gen.addLoadImmediate(Register.R0, 1234567890); 563 gen.addMove(Register.R1); 564 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL); 565 assertDrop(gen); 566 567 // Test swap. 568 gen = new ApfGenerator(MIN_APF_VERSION); 569 gen.addLoadImmediate(Register.R1, 1234567890); 570 gen.addSwap(); 571 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL); 572 assertDrop(gen); 573 gen = new ApfGenerator(MIN_APF_VERSION); 574 gen.addLoadImmediate(Register.R0, 1234567890); 575 gen.addSwap(); 576 gen.addJumpIfR0Equals(0, gen.DROP_LABEL); 577 assertDrop(gen); 578 579 // Test jump if bytes not equal. 580 gen = new ApfGenerator(MIN_APF_VERSION); 581 gen.addLoadImmediate(Register.R0, 1); 582 gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL); 583 program = gen.generate(); 584 assertEquals(6, program.length); 585 assertEquals((13 << 3) | (1 << 1) | 0, program[0]); 586 assertEquals(1, program[1]); 587 assertEquals(((20 << 3) | (1 << 1) | 0) - 256, program[2]); 588 assertEquals(1, program[3]); 589 assertEquals(1, program[4]); 590 assertEquals(123, program[5]); 591 assertDrop(program, new byte[MIN_PKT_SIZE], 0); 592 gen = new ApfGenerator(MIN_APF_VERSION); 593 gen.addLoadImmediate(Register.R0, 1); 594 gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL); 595 byte[] packet123 = {0,123,0,0,0,0,0,0,0,0,0,0,0,0,0}; 596 assertPass(gen, packet123, 0); 597 gen = new ApfGenerator(MIN_APF_VERSION); 598 gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL); 599 assertDrop(gen, packet123, 0); 600 gen = new ApfGenerator(MIN_APF_VERSION); 601 gen.addLoadImmediate(Register.R0, 1); 602 gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,30,4,5}, gen.DROP_LABEL); 603 byte[] packet12345 = {0,1,2,3,4,5,0,0,0,0,0,0,0,0,0}; 604 assertDrop(gen, packet12345, 0); 605 gen = new ApfGenerator(MIN_APF_VERSION); 606 gen.addLoadImmediate(Register.R0, 1); 607 gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,3,4,5}, gen.DROP_LABEL); 608 assertPass(gen, packet12345, 0); 609 } 610 611 @Test(expected = ApfGenerator.IllegalInstructionException.class) 612 public void testApfGeneratorWantsV2OrGreater() throws Exception { 613 // The minimum supported APF version is 2. 614 new ApfGenerator(1); 615 } 616 617 @Test 618 public void testApfDataOpcodesWantApfV3() throws IllegalInstructionException, Exception { 619 ApfGenerator gen = new ApfGenerator(MIN_APF_VERSION); 620 try { 621 gen.addStoreData(Register.R0, 0); 622 fail(); 623 } catch (IllegalInstructionException expected) { 624 /* pass */ 625 } 626 try { 627 gen.addLoadData(Register.R0, 0); 628 fail(); 629 } catch (IllegalInstructionException expected) { 630 /* pass */ 631 } 632 } 633 634 /** 635 * Test that the generator emits immediates using the shortest possible encoding. 636 */ 637 @Test 638 public void testImmediateEncoding() throws IllegalInstructionException { 639 final int LI_OPCODE = 13 << 3; 640 ApfGenerator gen; 641 642 // 0-byte immediate: li R0, 0 643 gen = new ApfGenerator(3); 644 gen.addLoadImmediate(Register.R0, 0); 645 assertProgramEquals(new byte[]{LI_OPCODE | (0 << 1)}, gen.generate()); 646 647 // 1-byte immediate: li R0, 42 648 gen = new ApfGenerator(3); 649 gen.addLoadImmediate(Register.R0, 42); 650 assertProgramEquals(new byte[]{LI_OPCODE | (1 << 1), 42}, gen.generate()); 651 652 // 2-byte immediate: li R1, 0x1234 653 gen = new ApfGenerator(3); 654 gen.addLoadImmediate(Register.R1, 0x1234); 655 assertProgramEquals(new byte[]{LI_OPCODE | (2 << 1) | 1 , 0x12, 0x34}, gen.generate()); 656 657 // 4-byte immediate: li R0, 0x12345678 658 gen = new ApfGenerator(3); 659 gen.addLoadImmediate(Register.R0, 0x12345678); 660 assertProgramEquals( 661 new byte[]{LI_OPCODE | (3 << 1), 0x12, 0x34, 0x56, 0x78}, 662 gen.generate()); 663 } 664 665 /** 666 * Test that the generator emits negative immediates using the shortest possible encoding. 667 */ 668 @Test 669 public void testNegativeImmediateEncoding() throws IllegalInstructionException { 670 final int LI_OPCODE = 13 << 3; 671 ApfGenerator gen; 672 673 // 1-byte negative immediate: li R0, -42 674 gen = new ApfGenerator(3); 675 gen.addLoadImmediate(Register.R0, -42); 676 assertProgramEquals(new byte[]{LI_OPCODE | (1 << 1), -42}, gen.generate()); 677 678 // 2-byte negative immediate: li R1, -0x1234 679 gen = new ApfGenerator(3); 680 gen.addLoadImmediate(Register.R1, -0x1122); 681 assertProgramEquals(new byte[]{LI_OPCODE | (2 << 1) | 1, (byte)0xEE, (byte)0xDE}, 682 gen.generate()); 683 684 // 4-byte negative immediate: li R0, -0x11223344 685 gen = new ApfGenerator(3); 686 gen.addLoadImmediate(Register.R0, -0x11223344); 687 assertProgramEquals( 688 new byte[]{LI_OPCODE | (3 << 1), (byte)0xEE, (byte)0xDD, (byte)0xCC, (byte)0xBC}, 689 gen.generate()); 690 } 691 692 @Test 693 public void testApfDataWrite() throws IllegalInstructionException, Exception { 694 byte[] packet = new byte[MIN_PKT_SIZE]; 695 byte[] data = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; 696 byte[] expected_data = data.clone(); 697 698 // No memory access instructions: should leave the data segment untouched. 699 ApfGenerator gen = new ApfGenerator(3); 700 assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data); 701 702 // Expect value 0x87654321 to be stored starting from address -11 from the end of the 703 // data buffer, in big-endian order. 704 gen = new ApfGenerator(3); 705 gen.addLoadImmediate(Register.R0, 0x87654321); 706 gen.addLoadImmediate(Register.R1, -5); 707 gen.addStoreData(Register.R0, -6); // -5 + -6 = -11 (offset +5 with data_len=16) 708 expected_data[5] = (byte)0x87; 709 expected_data[6] = (byte)0x65; 710 expected_data[7] = (byte)0x43; 711 expected_data[8] = (byte)0x21; 712 assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data); 713 } 714 715 @Test 716 public void testApfDataRead() throws IllegalInstructionException, Exception { 717 // Program that DROPs if address 10 (-6) contains 0x87654321. 718 ApfGenerator gen = new ApfGenerator(3); 719 gen.addLoadImmediate(Register.R1, 10); 720 gen.addLoadData(Register.R0, -16); // 10 + -16 = -6 (offset +10 with data_len=16) 721 gen.addJumpIfR0Equals(0x87654321, gen.DROP_LABEL); 722 byte[] program = gen.generate(); 723 byte[] packet = new byte[MIN_PKT_SIZE]; 724 725 // Content is incorrect (last byte does not match) -> PASS 726 byte[] data = new byte[16]; 727 data[10] = (byte)0x87; 728 data[11] = (byte)0x65; 729 data[12] = (byte)0x43; 730 data[13] = (byte)0x00; // != 0x21 731 byte[] expected_data = data.clone(); 732 assertDataMemoryContents(PASS, program, packet, data, expected_data); 733 734 // Fix the last byte -> conditional jump taken -> DROP 735 data[13] = (byte)0x21; 736 expected_data = data; 737 assertDataMemoryContents(DROP, program, packet, data, expected_data); 738 } 739 740 @Test 741 public void testApfDataReadModifyWrite() throws IllegalInstructionException, Exception { 742 ApfGenerator gen = new ApfGenerator(3); 743 gen.addLoadImmediate(Register.R1, -22); 744 gen.addLoadData(Register.R0, 0); // Load from address 32 -22 + 0 = 10 745 gen.addAdd(0x78453412); // 87654321 + 78453412 = FFAA7733 746 gen.addStoreData(Register.R0, 4); // Write back to address 32 -22 + 4 = 14 747 748 byte[] packet = new byte[MIN_PKT_SIZE]; 749 byte[] data = new byte[32]; 750 data[10] = (byte)0x87; 751 data[11] = (byte)0x65; 752 data[12] = (byte)0x43; 753 data[13] = (byte)0x21; 754 byte[] expected_data = data.clone(); 755 expected_data[14] = (byte)0xFF; 756 expected_data[15] = (byte)0xAA; 757 expected_data[16] = (byte)0x77; 758 expected_data[17] = (byte)0x33; 759 assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data); 760 } 761 762 @Test 763 public void testApfDataBoundChecking() throws IllegalInstructionException, Exception { 764 byte[] packet = new byte[MIN_PKT_SIZE]; 765 byte[] data = new byte[32]; 766 byte[] expected_data = data; 767 768 // Program that DROPs unconditionally. This is our the baseline. 769 ApfGenerator gen = new ApfGenerator(3); 770 gen.addLoadImmediate(Register.R0, 3); 771 gen.addLoadData(Register.R1, 7); 772 gen.addJump(gen.DROP_LABEL); 773 assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data); 774 775 // Same program as before, but this time we're trying to load past the end of the data. 776 gen = new ApfGenerator(3); 777 gen.addLoadImmediate(Register.R0, 20); 778 gen.addLoadData(Register.R1, 15); // 20 + 15 > 32 779 gen.addJump(gen.DROP_LABEL); // Not reached. 780 assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data); 781 782 // Subtracting an immediate should work... 783 gen = new ApfGenerator(3); 784 gen.addLoadImmediate(Register.R0, 20); 785 gen.addLoadData(Register.R1, -4); 786 gen.addJump(gen.DROP_LABEL); 787 assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data); 788 789 // ...and underflowing simply wraps around to the end of the buffer... 790 gen = new ApfGenerator(3); 791 gen.addLoadImmediate(Register.R0, 20); 792 gen.addLoadData(Register.R1, -30); 793 gen.addJump(gen.DROP_LABEL); 794 assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data); 795 796 // ...but doesn't allow accesses before the start of the buffer 797 gen = new ApfGenerator(3); 798 gen.addLoadImmediate(Register.R0, 20); 799 gen.addLoadData(Register.R1, -1000); 800 gen.addJump(gen.DROP_LABEL); // Not reached. 801 assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data); 802 } 803 804 /** 805 * Generate some BPF programs, translate them to APF, then run APF and BPF programs 806 * over packet traces and verify both programs filter out the same packets. 807 */ 808 @Test 809 public void testApfAgainstBpf() throws Exception { 810 String[] tcpdump_filters = new String[]{ "udp", "tcp", "icmp", "icmp6", "udp port 53", 811 "arp", "dst 239.255.255.250", "arp or tcp or udp port 53", "net 192.168.1.0/24", 812 "arp or icmp6 or portrange 53-54", "portrange 53-54 or portrange 100-50000", 813 "tcp[tcpflags] & (tcp-ack|tcp-fin) != 0 and (ip[2:2] > 57 or icmp)" }; 814 String pcap_filename = stageFile(R.raw.apf); 815 for (String tcpdump_filter : tcpdump_filters) { 816 byte[] apf_program = Bpf2Apf.convert(compileToBpf(tcpdump_filter)); 817 assertTrue("Failed to match for filter: " + tcpdump_filter, 818 compareBpfApf(tcpdump_filter, pcap_filename, apf_program)); 819 } 820 } 821 822 private class MockIpClientCallback extends IpClient.Callback { 823 private final ConditionVariable mGotApfProgram = new ConditionVariable(); 824 private byte[] mLastApfProgram; 825 826 @Override 827 public void installPacketFilter(byte[] filter) { 828 mLastApfProgram = filter; 829 mGotApfProgram.open(); 830 } 831 832 public void resetApfProgramWait() { 833 mGotApfProgram.close(); 834 } 835 836 public byte[] getApfProgram() { 837 assertTrue(mGotApfProgram.block(TIMEOUT_MS)); 838 return mLastApfProgram; 839 } 840 841 public void assertNoProgramUpdate() { 842 assertFalse(mGotApfProgram.block(TIMEOUT_MS)); 843 } 844 } 845 846 private static class TestApfFilter extends ApfFilter { 847 public final static byte[] MOCK_MAC_ADDR = {1,2,3,4,5,6}; 848 849 private FileDescriptor mWriteSocket; 850 private final long mFixedTimeMs = SystemClock.elapsedRealtime(); 851 852 public TestApfFilter(Context context, ApfConfiguration config, 853 IpClient.Callback ipClientCallback, IpConnectivityLog log) throws Exception { 854 super(context, config, InterfaceParams.getByName("lo"), ipClientCallback, log); 855 } 856 857 // Pretend an RA packet has been received and show it to ApfFilter. 858 public void pretendPacketReceived(byte[] packet) throws IOException, ErrnoException { 859 // ApfFilter's ReceiveThread will be waiting to read this. 860 Os.write(mWriteSocket, packet, 0, packet.length); 861 } 862 863 @Override 864 protected long currentTimeSeconds() { 865 return mFixedTimeMs / DateUtils.SECOND_IN_MILLIS; 866 } 867 868 @Override 869 void maybeStartFilter() { 870 mHardwareAddress = MOCK_MAC_ADDR; 871 installNewProgramLocked(); 872 873 // Create two sockets, "readSocket" and "mWriteSocket" and connect them together. 874 FileDescriptor readSocket = new FileDescriptor(); 875 mWriteSocket = new FileDescriptor(); 876 try { 877 Os.socketpair(AF_UNIX, SOCK_STREAM, 0, mWriteSocket, readSocket); 878 } catch (ErrnoException e) { 879 fail(); 880 return; 881 } 882 // Now pass readSocket to ReceiveThread as if it was setup to read raw RAs. 883 // This allows us to pretend RA packets have been recieved via pretendPacketReceived(). 884 mReceiveThread = new ReceiveThread(readSocket); 885 mReceiveThread.start(); 886 } 887 888 @Override 889 public void shutdown() { 890 super.shutdown(); 891 IoUtils.closeQuietly(mWriteSocket); 892 } 893 } 894 895 private static final int ETH_HEADER_LEN = 14; 896 private static final int ETH_DEST_ADDR_OFFSET = 0; 897 private static final int ETH_ETHERTYPE_OFFSET = 12; 898 private static final byte[] ETH_BROADCAST_MAC_ADDRESS = 899 {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff }; 900 901 private static final int IPV4_VERSION_IHL_OFFSET = ETH_HEADER_LEN + 0; 902 private static final int IPV4_PROTOCOL_OFFSET = ETH_HEADER_LEN + 9; 903 private static final int IPV4_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 16; 904 private static final byte[] IPV4_BROADCAST_ADDRESS = 905 {(byte) 255, (byte) 255, (byte) 255, (byte) 255}; 906 907 private static final int IPV6_NEXT_HEADER_OFFSET = ETH_HEADER_LEN + 6; 908 private static final int IPV6_HEADER_LEN = 40; 909 private static final int IPV6_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 24; 910 // The IPv6 all nodes address ff02::1 911 private static final byte[] IPV6_ALL_NODES_ADDRESS = 912 { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; 913 private static final byte[] IPV6_ALL_ROUTERS_ADDRESS = 914 { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 }; 915 916 private static final int ICMP6_TYPE_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN; 917 private static final int ICMP6_ROUTER_SOLICITATION = 133; 918 private static final int ICMP6_ROUTER_ADVERTISEMENT = 134; 919 private static final int ICMP6_NEIGHBOR_SOLICITATION = 135; 920 private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136; 921 922 private static final int ICMP6_RA_HEADER_LEN = 16; 923 private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET = 924 ETH_HEADER_LEN + IPV6_HEADER_LEN + 6; 925 private static final int ICMP6_RA_CHECKSUM_OFFSET = 926 ETH_HEADER_LEN + IPV6_HEADER_LEN + 2; 927 private static final int ICMP6_RA_OPTION_OFFSET = 928 ETH_HEADER_LEN + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN; 929 930 private static final int ICMP6_PREFIX_OPTION_TYPE = 3; 931 private static final int ICMP6_PREFIX_OPTION_LEN = 32; 932 private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET = 4; 933 private static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET = 8; 934 935 // From RFC6106: Recursive DNS Server option 936 private static final int ICMP6_RDNSS_OPTION_TYPE = 25; 937 // From RFC6106: DNS Search List option 938 private static final int ICMP6_DNSSL_OPTION_TYPE = 31; 939 940 // From RFC4191: Route Information option 941 private static final int ICMP6_ROUTE_INFO_OPTION_TYPE = 24; 942 // Above three options all have the same format: 943 private static final int ICMP6_4_BYTE_OPTION_LEN = 8; 944 private static final int ICMP6_4_BYTE_LIFETIME_OFFSET = 4; 945 private static final int ICMP6_4_BYTE_LIFETIME_LEN = 4; 946 947 private static final int UDP_HEADER_LEN = 8; 948 private static final int UDP_DESTINATION_PORT_OFFSET = ETH_HEADER_LEN + 22; 949 950 private static final int DHCP_CLIENT_PORT = 68; 951 private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 48; 952 953 private static final int ARP_HEADER_OFFSET = ETH_HEADER_LEN; 954 private static final byte[] ARP_IPV4_REQUEST_HEADER = { 955 0, 1, // Hardware type: Ethernet (1) 956 8, 0, // Protocol type: IP (0x0800) 957 6, // Hardware size: 6 958 4, // Protocol size: 4 959 0, 1 // Opcode: request (1) 960 }; 961 private static final byte[] ARP_IPV4_REPLY_HEADER = { 962 0, 1, // Hardware type: Ethernet (1) 963 8, 0, // Protocol type: IP (0x0800) 964 6, // Hardware size: 6 965 4, // Protocol size: 4 966 0, 2 // Opcode: reply (2) 967 }; 968 private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ETH_HEADER_LEN + 24; 969 970 private static final byte[] MOCK_IPV4_ADDR = {10, 0, 0, 1}; 971 private static final byte[] MOCK_BROADCAST_IPV4_ADDR = {10, 0, 31, (byte) 255}; // prefix = 19 972 private static final byte[] MOCK_MULTICAST_IPV4_ADDR = {(byte) 224, 0, 0, 1}; 973 private static final byte[] ANOTHER_IPV4_ADDR = {10, 0, 0, 2}; 974 private static final byte[] IPV4_ANY_HOST_ADDR = {0, 0, 0, 0}; 975 976 // Helper to initialize a default apfFilter. 977 private ApfFilter setupApfFilter(IpClient.Callback ipClientCallback, ApfConfiguration config) 978 throws Exception { 979 LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19); 980 LinkProperties lp = new LinkProperties(); 981 lp.addLinkAddress(link); 982 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog); 983 apfFilter.setLinkProperties(lp); 984 return apfFilter; 985 } 986 987 @Test 988 public void testApfFilterIPv4() throws Exception { 989 MockIpClientCallback ipClientCallback = new MockIpClientCallback(); 990 LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19); 991 LinkProperties lp = new LinkProperties(); 992 lp.addLinkAddress(link); 993 994 ApfConfiguration config = getDefaultConfig(); 995 config.multicastFilter = DROP_MULTICAST; 996 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog); 997 apfFilter.setLinkProperties(lp); 998 999 byte[] program = ipClientCallback.getApfProgram(); 1000 1001 // Verify empty packet of 100 zero bytes is passed 1002 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1003 assertPass(program, packet.array()); 1004 1005 // Verify unicast IPv4 packet is passed 1006 put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR); 1007 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 1008 put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_IPV4_ADDR); 1009 assertPass(program, packet.array()); 1010 1011 // Verify L2 unicast to IPv4 broadcast addresses is dropped (b/30231088) 1012 put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS); 1013 assertDrop(program, packet.array()); 1014 put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR); 1015 assertDrop(program, packet.array()); 1016 1017 // Verify multicast/broadcast IPv4, not DHCP to us, is dropped 1018 put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS); 1019 assertDrop(program, packet.array()); 1020 packet.put(IPV4_VERSION_IHL_OFFSET, (byte)0x45); 1021 assertDrop(program, packet.array()); 1022 packet.put(IPV4_PROTOCOL_OFFSET, (byte)IPPROTO_UDP); 1023 assertDrop(program, packet.array()); 1024 packet.putShort(UDP_DESTINATION_PORT_OFFSET, (short)DHCP_CLIENT_PORT); 1025 assertDrop(program, packet.array()); 1026 put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_MULTICAST_IPV4_ADDR); 1027 assertDrop(program, packet.array()); 1028 put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR); 1029 assertDrop(program, packet.array()); 1030 put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS); 1031 assertDrop(program, packet.array()); 1032 1033 // Verify broadcast IPv4 DHCP to us is passed 1034 put(packet, DHCP_CLIENT_MAC_OFFSET, TestApfFilter.MOCK_MAC_ADDR); 1035 assertPass(program, packet.array()); 1036 1037 // Verify unicast IPv4 DHCP to us is passed 1038 put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR); 1039 assertPass(program, packet.array()); 1040 1041 apfFilter.shutdown(); 1042 } 1043 1044 @Test 1045 public void testApfFilterIPv6() throws Exception { 1046 MockIpClientCallback ipClientCallback = new MockIpClientCallback(); 1047 ApfConfiguration config = getDefaultConfig(); 1048 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog); 1049 byte[] program = ipClientCallback.getApfProgram(); 1050 1051 // Verify empty IPv6 packet is passed 1052 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1053 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6); 1054 assertPass(program, packet.array()); 1055 1056 // Verify empty ICMPv6 packet is passed 1057 packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6); 1058 assertPass(program, packet.array()); 1059 1060 // Verify empty ICMPv6 NA packet is passed 1061 packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_NEIGHBOR_ANNOUNCEMENT); 1062 assertPass(program, packet.array()); 1063 1064 // Verify ICMPv6 NA to ff02::1 is dropped 1065 put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_NODES_ADDRESS); 1066 assertDrop(program, packet.array()); 1067 1068 // Verify ICMPv6 RS to any is dropped 1069 packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_SOLICITATION); 1070 assertDrop(program, packet.array()); 1071 put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_ROUTERS_ADDRESS); 1072 assertDrop(program, packet.array()); 1073 1074 apfFilter.shutdown(); 1075 } 1076 1077 @Test 1078 public void testApfFilterMulticast() throws Exception { 1079 final byte[] unicastIpv4Addr = {(byte)192,0,2,63}; 1080 final byte[] broadcastIpv4Addr = {(byte)192,0,2,(byte)255}; 1081 final byte[] multicastIpv4Addr = {(byte)224,0,0,1}; 1082 final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb}; 1083 1084 MockIpClientCallback ipClientCallback = new MockIpClientCallback(); 1085 LinkAddress link = new LinkAddress(InetAddress.getByAddress(unicastIpv4Addr), 24); 1086 LinkProperties lp = new LinkProperties(); 1087 lp.addLinkAddress(link); 1088 1089 ApfConfiguration config = getDefaultConfig(); 1090 config.ieee802_3Filter = DROP_802_3_FRAMES; 1091 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog); 1092 apfFilter.setLinkProperties(lp); 1093 1094 byte[] program = ipClientCallback.getApfProgram(); 1095 1096 // Construct IPv4 and IPv6 multicast packets. 1097 ByteBuffer mcastv4packet = ByteBuffer.wrap(new byte[100]); 1098 mcastv4packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 1099 put(mcastv4packet, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr); 1100 1101 ByteBuffer mcastv6packet = ByteBuffer.wrap(new byte[100]); 1102 mcastv6packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6); 1103 mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_UDP); 1104 put(mcastv6packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr); 1105 1106 // Construct IPv4 broadcast packet. 1107 ByteBuffer bcastv4packet1 = ByteBuffer.wrap(new byte[100]); 1108 bcastv4packet1.put(ETH_BROADCAST_MAC_ADDRESS); 1109 bcastv4packet1.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 1110 put(bcastv4packet1, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr); 1111 1112 ByteBuffer bcastv4packet2 = ByteBuffer.wrap(new byte[100]); 1113 bcastv4packet2.put(ETH_BROADCAST_MAC_ADDRESS); 1114 bcastv4packet2.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 1115 put(bcastv4packet2, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS); 1116 1117 // Construct IPv4 broadcast with L2 unicast address packet (b/30231088). 1118 ByteBuffer bcastv4unicastl2packet = ByteBuffer.wrap(new byte[100]); 1119 bcastv4unicastl2packet.put(TestApfFilter.MOCK_MAC_ADDR); 1120 bcastv4unicastl2packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 1121 put(bcastv4unicastl2packet, IPV4_DEST_ADDR_OFFSET, broadcastIpv4Addr); 1122 1123 // Verify initially disabled multicast filter is off 1124 assertPass(program, mcastv4packet.array()); 1125 assertPass(program, mcastv6packet.array()); 1126 assertPass(program, bcastv4packet1.array()); 1127 assertPass(program, bcastv4packet2.array()); 1128 assertPass(program, bcastv4unicastl2packet.array()); 1129 1130 // Turn on multicast filter and verify it works 1131 ipClientCallback.resetApfProgramWait(); 1132 apfFilter.setMulticastFilter(true); 1133 program = ipClientCallback.getApfProgram(); 1134 assertDrop(program, mcastv4packet.array()); 1135 assertDrop(program, mcastv6packet.array()); 1136 assertDrop(program, bcastv4packet1.array()); 1137 assertDrop(program, bcastv4packet2.array()); 1138 assertDrop(program, bcastv4unicastl2packet.array()); 1139 1140 // Turn off multicast filter and verify it's off 1141 ipClientCallback.resetApfProgramWait(); 1142 apfFilter.setMulticastFilter(false); 1143 program = ipClientCallback.getApfProgram(); 1144 assertPass(program, mcastv4packet.array()); 1145 assertPass(program, mcastv6packet.array()); 1146 assertPass(program, bcastv4packet1.array()); 1147 assertPass(program, bcastv4packet2.array()); 1148 assertPass(program, bcastv4unicastl2packet.array()); 1149 1150 // Verify it can be initialized to on 1151 ipClientCallback.resetApfProgramWait(); 1152 apfFilter.shutdown(); 1153 config.multicastFilter = DROP_MULTICAST; 1154 config.ieee802_3Filter = DROP_802_3_FRAMES; 1155 apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog); 1156 apfFilter.setLinkProperties(lp); 1157 program = ipClientCallback.getApfProgram(); 1158 assertDrop(program, mcastv4packet.array()); 1159 assertDrop(program, mcastv6packet.array()); 1160 assertDrop(program, bcastv4packet1.array()); 1161 assertDrop(program, bcastv4unicastl2packet.array()); 1162 1163 // Verify that ICMPv6 multicast is not dropped. 1164 mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6); 1165 assertPass(program, mcastv6packet.array()); 1166 1167 apfFilter.shutdown(); 1168 } 1169 1170 @Test 1171 public void testApfFilterMulticastPingWhileDozing() throws Exception { 1172 MockIpClientCallback ipClientCallback = new MockIpClientCallback(); 1173 ApfFilter apfFilter = setupApfFilter(ipClientCallback, getDefaultConfig()); 1174 1175 // Construct a multicast ICMPv6 ECHO request. 1176 final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb}; 1177 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1178 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6); 1179 packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6); 1180 packet.put(ICMP6_TYPE_OFFSET, (byte)ICMPV6_ECHO_REQUEST_TYPE); 1181 put(packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr); 1182 1183 // Normally, we let multicast pings alone... 1184 assertPass(ipClientCallback.getApfProgram(), packet.array()); 1185 1186 // ...and even while dozing... 1187 apfFilter.setDozeMode(true); 1188 assertPass(ipClientCallback.getApfProgram(), packet.array()); 1189 1190 // ...but when the multicast filter is also enabled, drop the multicast pings to save power. 1191 apfFilter.setMulticastFilter(true); 1192 assertDrop(ipClientCallback.getApfProgram(), packet.array()); 1193 1194 // However, we should still let through all other ICMPv6 types. 1195 ByteBuffer raPacket = ByteBuffer.wrap(packet.array().clone()); 1196 raPacket.put(ICMP6_TYPE_OFFSET, (byte)ICMPV6_ROUTER_ADVERTISEMENT); 1197 assertPass(ipClientCallback.getApfProgram(), raPacket.array()); 1198 1199 // Now wake up from doze mode to ensure that we no longer drop the packets. 1200 // (The multicast filter is still enabled at this point). 1201 apfFilter.setDozeMode(false); 1202 assertPass(ipClientCallback.getApfProgram(), packet.array()); 1203 1204 apfFilter.shutdown(); 1205 } 1206 1207 @Test 1208 public void testApfFilter802_3() throws Exception { 1209 MockIpClientCallback ipClientCallback = new MockIpClientCallback(); 1210 ApfConfiguration config = getDefaultConfig(); 1211 ApfFilter apfFilter = setupApfFilter(ipClientCallback, config); 1212 byte[] program = ipClientCallback.getApfProgram(); 1213 1214 // Verify empty packet of 100 zero bytes is passed 1215 // Note that eth-type = 0 makes it an IEEE802.3 frame 1216 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1217 assertPass(program, packet.array()); 1218 1219 // Verify empty packet with IPv4 is passed 1220 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 1221 assertPass(program, packet.array()); 1222 1223 // Verify empty IPv6 packet is passed 1224 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6); 1225 assertPass(program, packet.array()); 1226 1227 // Now turn on the filter 1228 ipClientCallback.resetApfProgramWait(); 1229 apfFilter.shutdown(); 1230 config.ieee802_3Filter = DROP_802_3_FRAMES; 1231 apfFilter = setupApfFilter(ipClientCallback, config); 1232 program = ipClientCallback.getApfProgram(); 1233 1234 // Verify that IEEE802.3 frame is dropped 1235 // In this case ethtype is used for payload length 1236 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)(100 - 14)); 1237 assertDrop(program, packet.array()); 1238 1239 // Verify that IPv4 (as example of Ethernet II) frame will pass 1240 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 1241 assertPass(program, packet.array()); 1242 1243 // Verify that IPv6 (as example of Ethernet II) frame will pass 1244 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6); 1245 assertPass(program, packet.array()); 1246 1247 apfFilter.shutdown(); 1248 } 1249 1250 @Test 1251 public void testApfFilterEthTypeBL() throws Exception { 1252 final int[] emptyBlackList = {}; 1253 final int[] ipv4BlackList = {ETH_P_IP}; 1254 final int[] ipv4Ipv6BlackList = {ETH_P_IP, ETH_P_IPV6}; 1255 1256 MockIpClientCallback ipClientCallback = new MockIpClientCallback(); 1257 ApfConfiguration config = getDefaultConfig(); 1258 ApfFilter apfFilter = setupApfFilter(ipClientCallback, config); 1259 byte[] program = ipClientCallback.getApfProgram(); 1260 1261 // Verify empty packet of 100 zero bytes is passed 1262 // Note that eth-type = 0 makes it an IEEE802.3 frame 1263 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1264 assertPass(program, packet.array()); 1265 1266 // Verify empty packet with IPv4 is passed 1267 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 1268 assertPass(program, packet.array()); 1269 1270 // Verify empty IPv6 packet is passed 1271 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6); 1272 assertPass(program, packet.array()); 1273 1274 // Now add IPv4 to the black list 1275 ipClientCallback.resetApfProgramWait(); 1276 apfFilter.shutdown(); 1277 config.ethTypeBlackList = ipv4BlackList; 1278 apfFilter = setupApfFilter(ipClientCallback, config); 1279 program = ipClientCallback.getApfProgram(); 1280 1281 // Verify that IPv4 frame will be dropped 1282 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 1283 assertDrop(program, packet.array()); 1284 1285 // Verify that IPv6 frame will pass 1286 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6); 1287 assertPass(program, packet.array()); 1288 1289 // Now let us have both IPv4 and IPv6 in the black list 1290 ipClientCallback.resetApfProgramWait(); 1291 apfFilter.shutdown(); 1292 config.ethTypeBlackList = ipv4Ipv6BlackList; 1293 apfFilter = setupApfFilter(ipClientCallback, config); 1294 program = ipClientCallback.getApfProgram(); 1295 1296 // Verify that IPv4 frame will be dropped 1297 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 1298 assertDrop(program, packet.array()); 1299 1300 // Verify that IPv6 frame will be dropped 1301 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6); 1302 assertDrop(program, packet.array()); 1303 1304 apfFilter.shutdown(); 1305 } 1306 1307 private byte[] getProgram(MockIpClientCallback cb, ApfFilter filter, LinkProperties lp) { 1308 cb.resetApfProgramWait(); 1309 filter.setLinkProperties(lp); 1310 return cb.getApfProgram(); 1311 } 1312 1313 private void verifyArpFilter(byte[] program, int filterResult) { 1314 // Verify ARP request packet 1315 assertPass(program, arpRequestBroadcast(MOCK_IPV4_ADDR)); 1316 assertVerdict(filterResult, program, arpRequestBroadcast(ANOTHER_IPV4_ADDR)); 1317 assertDrop(program, arpRequestBroadcast(IPV4_ANY_HOST_ADDR)); 1318 1319 // Verify unicast ARP reply packet is always accepted. 1320 assertPass(program, arpReplyUnicast(MOCK_IPV4_ADDR)); 1321 assertPass(program, arpReplyUnicast(ANOTHER_IPV4_ADDR)); 1322 assertPass(program, arpReplyUnicast(IPV4_ANY_HOST_ADDR)); 1323 1324 // Verify GARP reply packets are always filtered 1325 assertDrop(program, garpReply()); 1326 } 1327 1328 @Test 1329 public void testApfFilterArp() throws Exception { 1330 MockIpClientCallback ipClientCallback = new MockIpClientCallback(); 1331 ApfConfiguration config = getDefaultConfig(); 1332 config.multicastFilter = DROP_MULTICAST; 1333 config.ieee802_3Filter = DROP_802_3_FRAMES; 1334 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog); 1335 1336 // Verify initially ARP request filter is off, and GARP filter is on. 1337 verifyArpFilter(ipClientCallback.getApfProgram(), PASS); 1338 1339 // Inform ApfFilter of our address and verify ARP filtering is on 1340 LinkAddress linkAddress = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 24); 1341 LinkProperties lp = new LinkProperties(); 1342 assertTrue(lp.addLinkAddress(linkAddress)); 1343 verifyArpFilter(getProgram(ipClientCallback, apfFilter, lp), DROP); 1344 1345 // Inform ApfFilter of loss of IP and verify ARP filtering is off 1346 verifyArpFilter(getProgram(ipClientCallback, apfFilter, new LinkProperties()), PASS); 1347 1348 apfFilter.shutdown(); 1349 } 1350 1351 private static byte[] arpRequestBroadcast(byte[] tip) { 1352 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1353 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP); 1354 put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS); 1355 put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER); 1356 put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip); 1357 return packet.array(); 1358 } 1359 1360 private static byte[] arpReplyUnicast(byte[] tip) { 1361 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1362 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP); 1363 put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER); 1364 put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip); 1365 return packet.array(); 1366 } 1367 1368 private static byte[] garpReply() { 1369 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1370 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP); 1371 put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS); 1372 put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER); 1373 put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, IPV4_ANY_HOST_ADDR); 1374 return packet.array(); 1375 } 1376 1377 // Verify that the last program pushed to the IpClient.Callback properly filters the 1378 // given packet for the given lifetime. 1379 private void verifyRaLifetime(byte[] program, ByteBuffer packet, int lifetime) { 1380 final int FRACTION_OF_LIFETIME = 6; 1381 final int ageLimit = lifetime / FRACTION_OF_LIFETIME; 1382 1383 // Verify new program should drop RA for 1/6th its lifetime and pass afterwards. 1384 assertDrop(program, packet.array()); 1385 assertDrop(program, packet.array(), ageLimit); 1386 assertPass(program, packet.array(), ageLimit + 1); 1387 assertPass(program, packet.array(), lifetime); 1388 // Verify RA checksum is ignored 1389 final short originalChecksum = packet.getShort(ICMP6_RA_CHECKSUM_OFFSET); 1390 packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)12345); 1391 assertDrop(program, packet.array()); 1392 packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)-12345); 1393 assertDrop(program, packet.array()); 1394 packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, originalChecksum); 1395 1396 // Verify other changes to RA make it not match filter 1397 final byte originalFirstByte = packet.get(0); 1398 packet.put(0, (byte)-1); 1399 assertPass(program, packet.array()); 1400 packet.put(0, (byte)0); 1401 assertDrop(program, packet.array()); 1402 packet.put(0, originalFirstByte); 1403 } 1404 1405 // Test that when ApfFilter is shown the given packet, it generates a program to filter it 1406 // for the given lifetime. 1407 private void verifyRaLifetime(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback, 1408 ByteBuffer packet, int lifetime) throws IOException, ErrnoException { 1409 // Verify new program generated if ApfFilter witnesses RA 1410 ipClientCallback.resetApfProgramWait(); 1411 apfFilter.pretendPacketReceived(packet.array()); 1412 byte[] program = ipClientCallback.getApfProgram(); 1413 verifyRaLifetime(program, packet, lifetime); 1414 } 1415 1416 private void verifyRaEvent(RaEvent expected) { 1417 ArgumentCaptor<Parcelable> captor = ArgumentCaptor.forClass(Parcelable.class); 1418 verify(mLog, atLeastOnce()).log(captor.capture()); 1419 RaEvent got = lastRaEvent(captor.getAllValues()); 1420 if (!raEventEquals(expected, got)) { 1421 assertEquals(expected, got); // fail for printing an assertion error message. 1422 } 1423 } 1424 1425 private RaEvent lastRaEvent(List<Parcelable> events) { 1426 RaEvent got = null; 1427 for (Parcelable ev : events) { 1428 if (ev instanceof RaEvent) { 1429 got = (RaEvent) ev; 1430 } 1431 } 1432 return got; 1433 } 1434 1435 private boolean raEventEquals(RaEvent ev1, RaEvent ev2) { 1436 return (ev1 != null) && (ev2 != null) 1437 && (ev1.routerLifetime == ev2.routerLifetime) 1438 && (ev1.prefixValidLifetime == ev2.prefixValidLifetime) 1439 && (ev1.prefixPreferredLifetime == ev2.prefixPreferredLifetime) 1440 && (ev1.routeInfoLifetime == ev2.routeInfoLifetime) 1441 && (ev1.rdnssLifetime == ev2.rdnssLifetime) 1442 && (ev1.dnsslLifetime == ev2.dnsslLifetime); 1443 } 1444 1445 private void assertInvalidRa(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback, 1446 ByteBuffer packet) throws IOException, ErrnoException { 1447 ipClientCallback.resetApfProgramWait(); 1448 apfFilter.pretendPacketReceived(packet.array()); 1449 ipClientCallback.assertNoProgramUpdate(); 1450 } 1451 1452 @Test 1453 public void testApfFilterRa() throws Exception { 1454 MockIpClientCallback ipClientCallback = new MockIpClientCallback(); 1455 ApfConfiguration config = getDefaultConfig(); 1456 config.multicastFilter = DROP_MULTICAST; 1457 config.ieee802_3Filter = DROP_802_3_FRAMES; 1458 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog); 1459 byte[] program = ipClientCallback.getApfProgram(); 1460 1461 final int ROUTER_LIFETIME = 1000; 1462 final int PREFIX_VALID_LIFETIME = 200; 1463 final int PREFIX_PREFERRED_LIFETIME = 100; 1464 final int RDNSS_LIFETIME = 300; 1465 final int ROUTE_LIFETIME = 400; 1466 // Note that lifetime of 2000 will be ignored in favor of shorter route lifetime of 1000. 1467 final int DNSSL_LIFETIME = 2000; 1468 final int VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET = ETH_HEADER_LEN; 1469 // IPv6, traffic class = 0, flow label = 0x12345 1470 final int VERSION_TRAFFIC_CLASS_FLOW_LABEL = 0x60012345; 1471 1472 // Verify RA is passed the first time 1473 ByteBuffer basePacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]); 1474 basePacket.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6); 1475 basePacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET, 1476 VERSION_TRAFFIC_CLASS_FLOW_LABEL); 1477 basePacket.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6); 1478 basePacket.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_ADVERTISEMENT); 1479 basePacket.putShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET, (short)ROUTER_LIFETIME); 1480 basePacket.position(IPV6_DEST_ADDR_OFFSET); 1481 basePacket.put(IPV6_ALL_NODES_ADDRESS); 1482 assertPass(program, basePacket.array()); 1483 1484 verifyRaLifetime(apfFilter, ipClientCallback, basePacket, ROUTER_LIFETIME); 1485 verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, -1)); 1486 1487 ByteBuffer newFlowLabelPacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]); 1488 basePacket.clear(); 1489 newFlowLabelPacket.put(basePacket); 1490 // Check that changes are ignored in every byte of the flow label. 1491 newFlowLabelPacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET, 1492 VERSION_TRAFFIC_CLASS_FLOW_LABEL + 0x11111); 1493 1494 // Ensure zero-length options cause the packet to be silently skipped. 1495 // Do this before we test other packets. http://b/29586253 1496 ByteBuffer zeroLengthOptionPacket = ByteBuffer.wrap( 1497 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]); 1498 basePacket.clear(); 1499 zeroLengthOptionPacket.put(basePacket); 1500 zeroLengthOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE); 1501 zeroLengthOptionPacket.put((byte)0); 1502 assertInvalidRa(apfFilter, ipClientCallback, zeroLengthOptionPacket); 1503 1504 // Generate several RAs with different options and lifetimes, and verify when 1505 // ApfFilter is shown these packets, it generates programs to filter them for the 1506 // appropriate lifetime. 1507 ByteBuffer prefixOptionPacket = ByteBuffer.wrap( 1508 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_LEN]); 1509 basePacket.clear(); 1510 prefixOptionPacket.put(basePacket); 1511 prefixOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE); 1512 prefixOptionPacket.put((byte)(ICMP6_PREFIX_OPTION_LEN / 8)); 1513 prefixOptionPacket.putInt( 1514 ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET, 1515 PREFIX_PREFERRED_LIFETIME); 1516 prefixOptionPacket.putInt( 1517 ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET, 1518 PREFIX_VALID_LIFETIME); 1519 verifyRaLifetime( 1520 apfFilter, ipClientCallback, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME); 1521 verifyRaEvent(new RaEvent( 1522 ROUTER_LIFETIME, PREFIX_VALID_LIFETIME, PREFIX_PREFERRED_LIFETIME, -1, -1, -1)); 1523 1524 ByteBuffer rdnssOptionPacket = ByteBuffer.wrap( 1525 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]); 1526 basePacket.clear(); 1527 rdnssOptionPacket.put(basePacket); 1528 rdnssOptionPacket.put((byte)ICMP6_RDNSS_OPTION_TYPE); 1529 rdnssOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8)); 1530 rdnssOptionPacket.putInt( 1531 ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, RDNSS_LIFETIME); 1532 verifyRaLifetime(apfFilter, ipClientCallback, rdnssOptionPacket, RDNSS_LIFETIME); 1533 verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, RDNSS_LIFETIME, -1)); 1534 1535 ByteBuffer routeInfoOptionPacket = ByteBuffer.wrap( 1536 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]); 1537 basePacket.clear(); 1538 routeInfoOptionPacket.put(basePacket); 1539 routeInfoOptionPacket.put((byte)ICMP6_ROUTE_INFO_OPTION_TYPE); 1540 routeInfoOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8)); 1541 routeInfoOptionPacket.putInt( 1542 ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, ROUTE_LIFETIME); 1543 verifyRaLifetime(apfFilter, ipClientCallback, routeInfoOptionPacket, ROUTE_LIFETIME); 1544 verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, ROUTE_LIFETIME, -1, -1)); 1545 1546 ByteBuffer dnsslOptionPacket = ByteBuffer.wrap( 1547 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]); 1548 basePacket.clear(); 1549 dnsslOptionPacket.put(basePacket); 1550 dnsslOptionPacket.put((byte)ICMP6_DNSSL_OPTION_TYPE); 1551 dnsslOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8)); 1552 dnsslOptionPacket.putInt( 1553 ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, DNSSL_LIFETIME); 1554 verifyRaLifetime(apfFilter, ipClientCallback, dnsslOptionPacket, ROUTER_LIFETIME); 1555 verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, DNSSL_LIFETIME)); 1556 1557 // Verify that current program filters all five RAs: 1558 program = ipClientCallback.getApfProgram(); 1559 verifyRaLifetime(program, basePacket, ROUTER_LIFETIME); 1560 verifyRaLifetime(program, newFlowLabelPacket, ROUTER_LIFETIME); 1561 verifyRaLifetime(program, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME); 1562 verifyRaLifetime(program, rdnssOptionPacket, RDNSS_LIFETIME); 1563 verifyRaLifetime(program, routeInfoOptionPacket, ROUTE_LIFETIME); 1564 verifyRaLifetime(program, dnsslOptionPacket, ROUTER_LIFETIME); 1565 1566 apfFilter.shutdown(); 1567 } 1568 1569 /** 1570 * Stage a file for testing, i.e. make it native accessible. Given a resource ID, 1571 * copy that resource into the app's data directory and return the path to it. 1572 */ 1573 private String stageFile(int rawId) throws Exception { 1574 File file = new File(InstrumentationRegistry.getContext().getFilesDir(), "staged_file"); 1575 new File(file.getParent()).mkdirs(); 1576 InputStream in = null; 1577 OutputStream out = null; 1578 try { 1579 in = InstrumentationRegistry.getContext().getResources().openRawResource(rawId); 1580 out = new FileOutputStream(file); 1581 Streams.copy(in, out); 1582 } finally { 1583 if (in != null) in.close(); 1584 if (out != null) out.close(); 1585 } 1586 return file.getAbsolutePath(); 1587 } 1588 1589 private static void put(ByteBuffer buffer, int position, byte[] bytes) { 1590 final int original = buffer.position(); 1591 buffer.position(position); 1592 buffer.put(bytes); 1593 buffer.position(original); 1594 } 1595 1596 @Test 1597 public void testRaParsing() throws Exception { 1598 final int maxRandomPacketSize = 512; 1599 final Random r = new Random(); 1600 MockIpClientCallback cb = new MockIpClientCallback(); 1601 ApfConfiguration config = getDefaultConfig(); 1602 config.multicastFilter = DROP_MULTICAST; 1603 config.ieee802_3Filter = DROP_802_3_FRAMES; 1604 TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog); 1605 for (int i = 0; i < 1000; i++) { 1606 byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)]; 1607 r.nextBytes(packet); 1608 try { 1609 apfFilter.new Ra(packet, packet.length); 1610 } catch (ApfFilter.InvalidRaException e) { 1611 } catch (Exception e) { 1612 throw new Exception("bad packet: " + HexDump.toHexString(packet), e); 1613 } 1614 } 1615 } 1616 1617 @Test 1618 public void testRaProcessing() throws Exception { 1619 final int maxRandomPacketSize = 512; 1620 final Random r = new Random(); 1621 MockIpClientCallback cb = new MockIpClientCallback(); 1622 ApfConfiguration config = getDefaultConfig(); 1623 config.multicastFilter = DROP_MULTICAST; 1624 config.ieee802_3Filter = DROP_802_3_FRAMES; 1625 TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog); 1626 for (int i = 0; i < 1000; i++) { 1627 byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)]; 1628 r.nextBytes(packet); 1629 try { 1630 apfFilter.processRa(packet, packet.length); 1631 } catch (Exception e) { 1632 throw new Exception("bad packet: " + HexDump.toHexString(packet), e); 1633 } 1634 } 1635 } 1636 1637 /** 1638 * Call the APF interpreter to run {@code program} on {@code packet} with persistent memory 1639 * segment {@data} pretending the filter was installed {@code filter_age} seconds ago. 1640 */ 1641 private native static int apfSimulate(byte[] program, byte[] packet, byte[] data, 1642 int filter_age); 1643 1644 /** 1645 * Compile a tcpdump human-readable filter (e.g. "icmp" or "tcp port 54") into a BPF 1646 * prorgam and return a human-readable dump of the BPF program identical to "tcpdump -d". 1647 */ 1648 private native static String compileToBpf(String filter); 1649 1650 /** 1651 * Open packet capture file {@code pcap_filename} and filter the packets using tcpdump 1652 * human-readable filter (e.g. "icmp" or "tcp port 54") compiled to a BPF program and 1653 * at the same time using APF program {@code apf_program}. Return {@code true} if 1654 * both APF and BPF programs filter out exactly the same packets. 1655 */ 1656 private native static boolean compareBpfApf(String filter, String pcap_filename, 1657 byte[] apf_program); 1658 1659 @Test 1660 public void testBroadcastAddress() throws Exception { 1661 assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 0)); 1662 assertEqualsIp("0.0.0.0", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 32)); 1663 assertEqualsIp("0.0.3.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 22)); 1664 assertEqualsIp("0.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 8)); 1665 1666 assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 0)); 1667 assertEqualsIp("10.0.0.1", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 32)); 1668 assertEqualsIp("10.0.0.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 24)); 1669 assertEqualsIp("10.0.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 16)); 1670 } 1671 1672 public void assertEqualsIp(String expected, int got) throws Exception { 1673 int want = bytesToBEInt(InetAddress.getByName(expected).getAddress()); 1674 assertEquals(want, got); 1675 } 1676 } 1677