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