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