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.server.util.NetworkStackConstants.ICMPV6_ECHO_REQUEST_TYPE; 30 import static com.android.server.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.networkstack.apishim.NetworkInformationShimImpl; 71 import com.android.server.networkstack.tests.R; 72 import com.android.server.util.NetworkStackConstants; 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 1060 private static final int ICMP6_TYPE_OFFSET = IP_HEADER_OFFSET + IPV6_HEADER_LEN; 1061 private static final int ICMP6_ROUTER_SOLICITATION = 133; 1062 private static final int ICMP6_ROUTER_ADVERTISEMENT = 134; 1063 private static final int ICMP6_NEIGHBOR_SOLICITATION = 135; 1064 private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136; 1065 1066 private static final int ICMP6_RA_HEADER_LEN = 16; 1067 private static final int ICMP6_RA_CHECKSUM_OFFSET = 1068 IP_HEADER_OFFSET + IPV6_HEADER_LEN + 2; 1069 private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET = 1070 IP_HEADER_OFFSET + IPV6_HEADER_LEN + 6; 1071 private static final int ICMP6_RA_REACHABLE_TIME_OFFSET = 1072 IP_HEADER_OFFSET + IPV6_HEADER_LEN + 8; 1073 private static final int ICMP6_RA_RETRANSMISSION_TIMER_OFFSET = 1074 IP_HEADER_OFFSET + IPV6_HEADER_LEN + 12; 1075 private static final int ICMP6_RA_OPTION_OFFSET = 1076 IP_HEADER_OFFSET + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN; 1077 1078 private static final int ICMP6_PREFIX_OPTION_TYPE = 3; 1079 private static final int ICMP6_PREFIX_OPTION_LEN = 32; 1080 private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET = 4; 1081 private static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET = 8; 1082 1083 // From RFC6106: Recursive DNS Server option 1084 private static final int ICMP6_RDNSS_OPTION_TYPE = 25; 1085 // From RFC6106: DNS Search List option 1086 private static final int ICMP6_DNSSL_OPTION_TYPE = 31; 1087 1088 // From RFC4191: Route Information option 1089 private static final int ICMP6_ROUTE_INFO_OPTION_TYPE = 24; 1090 // Above three options all have the same format: 1091 private static final int ICMP6_4_BYTE_OPTION_LEN = 8; 1092 private static final int ICMP6_4_BYTE_LIFETIME_OFFSET = 4; 1093 private static final int ICMP6_4_BYTE_LIFETIME_LEN = 4; 1094 1095 private static final int UDP_HEADER_LEN = 8; 1096 private static final int UDP_DESTINATION_PORT_OFFSET = ETH_HEADER_LEN + 22; 1097 1098 private static final int DHCP_CLIENT_PORT = 68; 1099 private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 48; 1100 1101 private static final int ARP_HEADER_OFFSET = ETH_HEADER_LEN; 1102 private static final byte[] ARP_IPV4_REQUEST_HEADER = { 1103 0, 1, // Hardware type: Ethernet (1) 1104 8, 0, // Protocol type: IP (0x0800) 1105 6, // Hardware size: 6 1106 4, // Protocol size: 4 1107 0, 1 // Opcode: request (1) 1108 }; 1109 private static final byte[] ARP_IPV4_REPLY_HEADER = { 1110 0, 1, // Hardware type: Ethernet (1) 1111 8, 0, // Protocol type: IP (0x0800) 1112 6, // Hardware size: 6 1113 4, // Protocol size: 4 1114 0, 2 // Opcode: reply (2) 1115 }; 1116 private static final int ARP_SOURCE_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 14; 1117 private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 24; 1118 1119 private static final byte[] MOCK_IPV4_ADDR = {10, 0, 0, 1}; 1120 private static final byte[] MOCK_BROADCAST_IPV4_ADDR = {10, 0, 31, (byte) 255}; // prefix = 19 1121 private static final byte[] MOCK_MULTICAST_IPV4_ADDR = {(byte) 224, 0, 0, 1}; 1122 private static final byte[] ANOTHER_IPV4_ADDR = {10, 0, 0, 2}; 1123 private static final byte[] IPV4_SOURCE_ADDR = {10, 0, 0, 3}; 1124 private static final byte[] ANOTHER_IPV4_SOURCE_ADDR = {(byte) 192, 0, 2, 1}; 1125 private static final byte[] BUG_PROBE_SOURCE_ADDR1 = {0, 0, 1, 2}; 1126 private static final byte[] BUG_PROBE_SOURCE_ADDR2 = {3, 4, 0, 0}; 1127 private static final byte[] IPV4_ANY_HOST_ADDR = {0, 0, 0, 0}; 1128 1129 // Helper to initialize a default apfFilter. setupApfFilter( IpClientCallbacksWrapper ipClientCallback, ApfConfiguration config)1130 private ApfFilter setupApfFilter( 1131 IpClientCallbacksWrapper ipClientCallback, ApfConfiguration config) throws Exception { 1132 LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19); 1133 LinkProperties lp = new LinkProperties(); 1134 lp.addLinkAddress(link); 1135 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog); 1136 apfFilter.setLinkProperties(lp); 1137 return apfFilter; 1138 } 1139 setIpv4VersionFields(ByteBuffer packet)1140 private static void setIpv4VersionFields(ByteBuffer packet) { 1141 packet.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IP); 1142 packet.put(IP_HEADER_OFFSET, (byte) 0x45); 1143 } 1144 setIpv6VersionFields(ByteBuffer packet)1145 private static void setIpv6VersionFields(ByteBuffer packet) { 1146 packet.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IPV6); 1147 packet.put(IP_HEADER_OFFSET, (byte) 0x60); 1148 } 1149 makeIpv4Packet(int proto)1150 private static ByteBuffer makeIpv4Packet(int proto) { 1151 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1152 setIpv4VersionFields(packet); 1153 packet.put(IPV4_PROTOCOL_OFFSET, (byte) proto); 1154 return packet; 1155 } 1156 makeIpv6Packet(int nextHeader)1157 private static ByteBuffer makeIpv6Packet(int nextHeader) { 1158 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1159 setIpv6VersionFields(packet); 1160 packet.put(IPV6_NEXT_HEADER_OFFSET, (byte) nextHeader); 1161 return packet; 1162 } 1163 1164 @Test testApfFilterIPv4()1165 public void testApfFilterIPv4() throws Exception { 1166 MockIpClientCallback ipClientCallback = new MockIpClientCallback(); 1167 LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19); 1168 LinkProperties lp = new LinkProperties(); 1169 lp.addLinkAddress(link); 1170 1171 ApfConfiguration config = getDefaultConfig(); 1172 config.multicastFilter = DROP_MULTICAST; 1173 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog); 1174 apfFilter.setLinkProperties(lp); 1175 1176 byte[] program = ipClientCallback.getApfProgram(); 1177 1178 // Verify empty packet of 100 zero bytes is passed 1179 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1180 assertPass(program, packet.array()); 1181 1182 // Verify unicast IPv4 packet is passed 1183 put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR); 1184 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 1185 put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_IPV4_ADDR); 1186 assertPass(program, packet.array()); 1187 1188 // Verify L2 unicast to IPv4 broadcast addresses is dropped (b/30231088) 1189 put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS); 1190 assertDrop(program, packet.array()); 1191 put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR); 1192 assertDrop(program, packet.array()); 1193 1194 // Verify multicast/broadcast IPv4, not DHCP to us, is dropped 1195 put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS); 1196 assertDrop(program, packet.array()); 1197 packet.put(IP_HEADER_OFFSET, (byte) 0x45); 1198 assertDrop(program, packet.array()); 1199 packet.put(IPV4_PROTOCOL_OFFSET, (byte)IPPROTO_UDP); 1200 assertDrop(program, packet.array()); 1201 packet.putShort(UDP_DESTINATION_PORT_OFFSET, (short)DHCP_CLIENT_PORT); 1202 assertDrop(program, packet.array()); 1203 put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_MULTICAST_IPV4_ADDR); 1204 assertDrop(program, packet.array()); 1205 put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR); 1206 assertDrop(program, packet.array()); 1207 put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS); 1208 assertDrop(program, packet.array()); 1209 1210 // Verify broadcast IPv4 DHCP to us is passed 1211 put(packet, DHCP_CLIENT_MAC_OFFSET, TestApfFilter.MOCK_MAC_ADDR); 1212 assertPass(program, packet.array()); 1213 1214 // Verify unicast IPv4 DHCP to us is passed 1215 put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR); 1216 assertPass(program, packet.array()); 1217 1218 apfFilter.shutdown(); 1219 } 1220 1221 @Test testApfFilterIPv6()1222 public void testApfFilterIPv6() throws Exception { 1223 MockIpClientCallback ipClientCallback = new MockIpClientCallback(); 1224 ApfConfiguration config = getDefaultConfig(); 1225 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog); 1226 byte[] program = ipClientCallback.getApfProgram(); 1227 1228 // Verify empty IPv6 packet is passed 1229 ByteBuffer packet = makeIpv6Packet(IPPROTO_UDP); 1230 assertPass(program, packet.array()); 1231 1232 // Verify empty ICMPv6 packet is passed 1233 packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6); 1234 assertPass(program, packet.array()); 1235 1236 // Verify empty ICMPv6 NA packet is passed 1237 packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_NEIGHBOR_ANNOUNCEMENT); 1238 assertPass(program, packet.array()); 1239 1240 // Verify ICMPv6 NA to ff02::1 is dropped 1241 put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_NODES_ADDRESS); 1242 assertDrop(program, packet.array()); 1243 1244 // Verify ICMPv6 RS to any is dropped 1245 packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_SOLICITATION); 1246 assertDrop(program, packet.array()); 1247 put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_ROUTERS_ADDRESS); 1248 assertDrop(program, packet.array()); 1249 1250 apfFilter.shutdown(); 1251 } 1252 1253 @Test testApfFilterMulticast()1254 public void testApfFilterMulticast() throws Exception { 1255 final byte[] unicastIpv4Addr = {(byte)192,0,2,63}; 1256 final byte[] broadcastIpv4Addr = {(byte)192,0,2,(byte)255}; 1257 final byte[] multicastIpv4Addr = {(byte)224,0,0,1}; 1258 final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb}; 1259 1260 MockIpClientCallback ipClientCallback = new MockIpClientCallback(); 1261 LinkAddress link = new LinkAddress(InetAddress.getByAddress(unicastIpv4Addr), 24); 1262 LinkProperties lp = new LinkProperties(); 1263 lp.addLinkAddress(link); 1264 1265 ApfConfiguration config = getDefaultConfig(); 1266 config.ieee802_3Filter = DROP_802_3_FRAMES; 1267 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog); 1268 apfFilter.setLinkProperties(lp); 1269 1270 byte[] program = ipClientCallback.getApfProgram(); 1271 1272 // Construct IPv4 and IPv6 multicast packets. 1273 ByteBuffer mcastv4packet = makeIpv4Packet(IPPROTO_UDP); 1274 put(mcastv4packet, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr); 1275 1276 ByteBuffer mcastv6packet = makeIpv6Packet(IPPROTO_UDP); 1277 put(mcastv6packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr); 1278 1279 // Construct IPv4 broadcast packet. 1280 ByteBuffer bcastv4packet1 = makeIpv4Packet(IPPROTO_UDP); 1281 bcastv4packet1.put(ETH_BROADCAST_MAC_ADDRESS); 1282 bcastv4packet1.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 1283 put(bcastv4packet1, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr); 1284 1285 ByteBuffer bcastv4packet2 = makeIpv4Packet(IPPROTO_UDP); 1286 bcastv4packet2.put(ETH_BROADCAST_MAC_ADDRESS); 1287 bcastv4packet2.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 1288 put(bcastv4packet2, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS); 1289 1290 // Construct IPv4 broadcast with L2 unicast address packet (b/30231088). 1291 ByteBuffer bcastv4unicastl2packet = makeIpv4Packet(IPPROTO_UDP); 1292 bcastv4unicastl2packet.put(TestApfFilter.MOCK_MAC_ADDR); 1293 bcastv4unicastl2packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 1294 put(bcastv4unicastl2packet, IPV4_DEST_ADDR_OFFSET, broadcastIpv4Addr); 1295 1296 // Verify initially disabled multicast filter is off 1297 assertPass(program, mcastv4packet.array()); 1298 assertPass(program, mcastv6packet.array()); 1299 assertPass(program, bcastv4packet1.array()); 1300 assertPass(program, bcastv4packet2.array()); 1301 assertPass(program, bcastv4unicastl2packet.array()); 1302 1303 // Turn on multicast filter and verify it works 1304 ipClientCallback.resetApfProgramWait(); 1305 apfFilter.setMulticastFilter(true); 1306 program = ipClientCallback.getApfProgram(); 1307 assertDrop(program, mcastv4packet.array()); 1308 assertDrop(program, mcastv6packet.array()); 1309 assertDrop(program, bcastv4packet1.array()); 1310 assertDrop(program, bcastv4packet2.array()); 1311 assertDrop(program, bcastv4unicastl2packet.array()); 1312 1313 // Turn off multicast filter and verify it's off 1314 ipClientCallback.resetApfProgramWait(); 1315 apfFilter.setMulticastFilter(false); 1316 program = ipClientCallback.getApfProgram(); 1317 assertPass(program, mcastv4packet.array()); 1318 assertPass(program, mcastv6packet.array()); 1319 assertPass(program, bcastv4packet1.array()); 1320 assertPass(program, bcastv4packet2.array()); 1321 assertPass(program, bcastv4unicastl2packet.array()); 1322 1323 // Verify it can be initialized to on 1324 ipClientCallback.resetApfProgramWait(); 1325 apfFilter.shutdown(); 1326 config.multicastFilter = DROP_MULTICAST; 1327 config.ieee802_3Filter = DROP_802_3_FRAMES; 1328 apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog); 1329 apfFilter.setLinkProperties(lp); 1330 program = ipClientCallback.getApfProgram(); 1331 assertDrop(program, mcastv4packet.array()); 1332 assertDrop(program, mcastv6packet.array()); 1333 assertDrop(program, bcastv4packet1.array()); 1334 assertDrop(program, bcastv4unicastl2packet.array()); 1335 1336 // Verify that ICMPv6 multicast is not dropped. 1337 mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6); 1338 assertPass(program, mcastv6packet.array()); 1339 1340 apfFilter.shutdown(); 1341 } 1342 1343 @Test testApfFilterMulticastPingWhileDozing()1344 public void testApfFilterMulticastPingWhileDozing() throws Exception { 1345 MockIpClientCallback ipClientCallback = new MockIpClientCallback(); 1346 ApfFilter apfFilter = setupApfFilter(ipClientCallback, getDefaultConfig()); 1347 1348 // Construct a multicast ICMPv6 ECHO request. 1349 final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb}; 1350 ByteBuffer packet = makeIpv6Packet(IPPROTO_ICMPV6); 1351 packet.put(ICMP6_TYPE_OFFSET, (byte)ICMPV6_ECHO_REQUEST_TYPE); 1352 put(packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr); 1353 1354 // Normally, we let multicast pings alone... 1355 assertPass(ipClientCallback.getApfProgram(), packet.array()); 1356 1357 // ...and even while dozing... 1358 apfFilter.setDozeMode(true); 1359 assertPass(ipClientCallback.getApfProgram(), packet.array()); 1360 1361 // ...but when the multicast filter is also enabled, drop the multicast pings to save power. 1362 apfFilter.setMulticastFilter(true); 1363 assertDrop(ipClientCallback.getApfProgram(), packet.array()); 1364 1365 // However, we should still let through all other ICMPv6 types. 1366 ByteBuffer raPacket = ByteBuffer.wrap(packet.array().clone()); 1367 setIpv6VersionFields(packet); 1368 packet.put(IPV6_NEXT_HEADER_OFFSET, (byte) IPPROTO_ICMPV6); 1369 raPacket.put(ICMP6_TYPE_OFFSET, (byte) NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT); 1370 assertPass(ipClientCallback.getApfProgram(), raPacket.array()); 1371 1372 // Now wake up from doze mode to ensure that we no longer drop the packets. 1373 // (The multicast filter is still enabled at this point). 1374 apfFilter.setDozeMode(false); 1375 assertPass(ipClientCallback.getApfProgram(), packet.array()); 1376 1377 apfFilter.shutdown(); 1378 } 1379 1380 @Test testApfFilter802_3()1381 public void testApfFilter802_3() throws Exception { 1382 MockIpClientCallback ipClientCallback = new MockIpClientCallback(); 1383 ApfConfiguration config = getDefaultConfig(); 1384 ApfFilter apfFilter = setupApfFilter(ipClientCallback, config); 1385 byte[] program = ipClientCallback.getApfProgram(); 1386 1387 // Verify empty packet of 100 zero bytes is passed 1388 // Note that eth-type = 0 makes it an IEEE802.3 frame 1389 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1390 assertPass(program, packet.array()); 1391 1392 // Verify empty packet with IPv4 is passed 1393 setIpv4VersionFields(packet); 1394 assertPass(program, packet.array()); 1395 1396 // Verify empty IPv6 packet is passed 1397 setIpv6VersionFields(packet); 1398 assertPass(program, packet.array()); 1399 1400 // Now turn on the filter 1401 ipClientCallback.resetApfProgramWait(); 1402 apfFilter.shutdown(); 1403 config.ieee802_3Filter = DROP_802_3_FRAMES; 1404 apfFilter = setupApfFilter(ipClientCallback, config); 1405 program = ipClientCallback.getApfProgram(); 1406 1407 // Verify that IEEE802.3 frame is dropped 1408 // In this case ethtype is used for payload length 1409 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)(100 - 14)); 1410 assertDrop(program, packet.array()); 1411 1412 // Verify that IPv4 (as example of Ethernet II) frame will pass 1413 setIpv4VersionFields(packet); 1414 assertPass(program, packet.array()); 1415 1416 // Verify that IPv6 (as example of Ethernet II) frame will pass 1417 setIpv6VersionFields(packet); 1418 assertPass(program, packet.array()); 1419 1420 apfFilter.shutdown(); 1421 } 1422 1423 @Test testApfFilterEthTypeBL()1424 public void testApfFilterEthTypeBL() throws Exception { 1425 final int[] emptyBlackList = {}; 1426 final int[] ipv4BlackList = {ETH_P_IP}; 1427 final int[] ipv4Ipv6BlackList = {ETH_P_IP, ETH_P_IPV6}; 1428 1429 MockIpClientCallback ipClientCallback = new MockIpClientCallback(); 1430 ApfConfiguration config = getDefaultConfig(); 1431 ApfFilter apfFilter = setupApfFilter(ipClientCallback, config); 1432 byte[] program = ipClientCallback.getApfProgram(); 1433 1434 // Verify empty packet of 100 zero bytes is passed 1435 // Note that eth-type = 0 makes it an IEEE802.3 frame 1436 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1437 assertPass(program, packet.array()); 1438 1439 // Verify empty packet with IPv4 is passed 1440 setIpv4VersionFields(packet); 1441 assertPass(program, packet.array()); 1442 1443 // Verify empty IPv6 packet is passed 1444 setIpv6VersionFields(packet); 1445 assertPass(program, packet.array()); 1446 1447 // Now add IPv4 to the black list 1448 ipClientCallback.resetApfProgramWait(); 1449 apfFilter.shutdown(); 1450 config.ethTypeBlackList = ipv4BlackList; 1451 apfFilter = setupApfFilter(ipClientCallback, config); 1452 program = ipClientCallback.getApfProgram(); 1453 1454 // Verify that IPv4 frame will be dropped 1455 setIpv4VersionFields(packet); 1456 assertDrop(program, packet.array()); 1457 1458 // Verify that IPv6 frame will pass 1459 setIpv6VersionFields(packet); 1460 assertPass(program, packet.array()); 1461 1462 // Now let us have both IPv4 and IPv6 in the black list 1463 ipClientCallback.resetApfProgramWait(); 1464 apfFilter.shutdown(); 1465 config.ethTypeBlackList = ipv4Ipv6BlackList; 1466 apfFilter = setupApfFilter(ipClientCallback, config); 1467 program = ipClientCallback.getApfProgram(); 1468 1469 // Verify that IPv4 frame will be dropped 1470 setIpv4VersionFields(packet); 1471 assertDrop(program, packet.array()); 1472 1473 // Verify that IPv6 frame will be dropped 1474 setIpv6VersionFields(packet); 1475 assertDrop(program, packet.array()); 1476 1477 apfFilter.shutdown(); 1478 } 1479 getProgram(MockIpClientCallback cb, ApfFilter filter, LinkProperties lp)1480 private byte[] getProgram(MockIpClientCallback cb, ApfFilter filter, LinkProperties lp) { 1481 cb.resetApfProgramWait(); 1482 filter.setLinkProperties(lp); 1483 return cb.getApfProgram(); 1484 } 1485 verifyArpFilter(byte[] program, int filterResult)1486 private void verifyArpFilter(byte[] program, int filterResult) { 1487 // Verify ARP request packet 1488 assertPass(program, arpRequestBroadcast(MOCK_IPV4_ADDR)); 1489 assertVerdict(filterResult, program, arpRequestBroadcast(ANOTHER_IPV4_ADDR)); 1490 assertDrop(program, arpRequestBroadcast(IPV4_ANY_HOST_ADDR)); 1491 1492 // Verify ARP reply packets from different source ip 1493 assertDrop(program, arpReply(IPV4_ANY_HOST_ADDR, IPV4_ANY_HOST_ADDR)); 1494 assertPass(program, arpReply(ANOTHER_IPV4_SOURCE_ADDR, IPV4_ANY_HOST_ADDR)); 1495 assertPass(program, arpReply(BUG_PROBE_SOURCE_ADDR1, IPV4_ANY_HOST_ADDR)); 1496 assertPass(program, arpReply(BUG_PROBE_SOURCE_ADDR2, IPV4_ANY_HOST_ADDR)); 1497 1498 // Verify unicast ARP reply packet is always accepted. 1499 assertPass(program, arpReply(IPV4_SOURCE_ADDR, MOCK_IPV4_ADDR)); 1500 assertPass(program, arpReply(IPV4_SOURCE_ADDR, ANOTHER_IPV4_ADDR)); 1501 assertPass(program, arpReply(IPV4_SOURCE_ADDR, IPV4_ANY_HOST_ADDR)); 1502 1503 // Verify GARP reply packets are always filtered 1504 assertDrop(program, garpReply()); 1505 } 1506 1507 @Test testApfFilterArp()1508 public void testApfFilterArp() throws Exception { 1509 MockIpClientCallback ipClientCallback = new MockIpClientCallback(); 1510 ApfConfiguration config = getDefaultConfig(); 1511 config.multicastFilter = DROP_MULTICAST; 1512 config.ieee802_3Filter = DROP_802_3_FRAMES; 1513 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog); 1514 1515 // Verify initially ARP request filter is off, and GARP filter is on. 1516 verifyArpFilter(ipClientCallback.getApfProgram(), PASS); 1517 1518 // Inform ApfFilter of our address and verify ARP filtering is on 1519 LinkAddress linkAddress = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 24); 1520 LinkProperties lp = new LinkProperties(); 1521 assertTrue(lp.addLinkAddress(linkAddress)); 1522 verifyArpFilter(getProgram(ipClientCallback, apfFilter, lp), DROP); 1523 1524 // Inform ApfFilter of loss of IP and verify ARP filtering is off 1525 verifyArpFilter(getProgram(ipClientCallback, apfFilter, new LinkProperties()), PASS); 1526 1527 apfFilter.shutdown(); 1528 } 1529 arpReply(byte[] sip, byte[] tip)1530 private static byte[] arpReply(byte[] sip, byte[] tip) { 1531 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1532 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP); 1533 put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER); 1534 put(packet, ARP_SOURCE_IP_ADDRESS_OFFSET, sip); 1535 put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip); 1536 return packet.array(); 1537 } 1538 arpRequestBroadcast(byte[] tip)1539 private static byte[] arpRequestBroadcast(byte[] tip) { 1540 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1541 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP); 1542 put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS); 1543 put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REQUEST_HEADER); 1544 put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip); 1545 return packet.array(); 1546 } 1547 garpReply()1548 private static byte[] garpReply() { 1549 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1550 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP); 1551 put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS); 1552 put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER); 1553 put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, IPV4_ANY_HOST_ADDR); 1554 return packet.array(); 1555 } 1556 1557 private static final byte[] IPV4_KEEPALIVE_SRC_ADDR = {10, 0, 0, 5}; 1558 private static final byte[] IPV4_KEEPALIVE_DST_ADDR = {10, 0, 0, 6}; 1559 private static final byte[] IPV4_ANOTHER_ADDR = {10, 0 , 0, 7}; 1560 private static final byte[] IPV6_KEEPALIVE_SRC_ADDR = 1561 {(byte) 0x24, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xfa, (byte) 0xf1}; 1562 private static final byte[] IPV6_KEEPALIVE_DST_ADDR = 1563 {(byte) 0x24, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xfa, (byte) 0xf2}; 1564 private static final byte[] IPV6_ANOTHER_ADDR = 1565 {(byte) 0x24, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xfa, (byte) 0xf5}; 1566 1567 @Test testApfFilterKeepaliveAck()1568 public void testApfFilterKeepaliveAck() throws Exception { 1569 final MockIpClientCallback cb = new MockIpClientCallback(); 1570 final ApfConfiguration config = getDefaultConfig(); 1571 config.multicastFilter = DROP_MULTICAST; 1572 config.ieee802_3Filter = DROP_802_3_FRAMES; 1573 final TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog); 1574 byte[] program; 1575 final int srcPort = 12345; 1576 final int dstPort = 54321; 1577 final int seqNum = 2123456789; 1578 final int ackNum = 1234567890; 1579 final int anotherSrcPort = 23456; 1580 final int anotherDstPort = 65432; 1581 final int anotherSeqNum = 2123456780; 1582 final int anotherAckNum = 1123456789; 1583 final int slot1 = 1; 1584 final int slot2 = 2; 1585 final int window = 14480; 1586 final int windowScale = 4; 1587 1588 // src: 10.0.0.5, port: 12345 1589 // dst: 10.0.0.6, port: 54321 1590 InetAddress srcAddr = InetAddress.getByAddress(IPV4_KEEPALIVE_SRC_ADDR); 1591 InetAddress dstAddr = InetAddress.getByAddress(IPV4_KEEPALIVE_DST_ADDR); 1592 1593 final TcpKeepalivePacketDataParcelable parcel = new TcpKeepalivePacketDataParcelable(); 1594 parcel.srcAddress = srcAddr.getAddress(); 1595 parcel.srcPort = srcPort; 1596 parcel.dstAddress = dstAddr.getAddress(); 1597 parcel.dstPort = dstPort; 1598 parcel.seq = seqNum; 1599 parcel.ack = ackNum; 1600 1601 apfFilter.addTcpKeepalivePacketFilter(slot1, parcel); 1602 program = cb.getApfProgram(); 1603 1604 // Verify IPv4 keepalive ack packet is dropped 1605 // src: 10.0.0.6, port: 54321 1606 // dst: 10.0.0.5, port: 12345 1607 assertDrop(program, 1608 ipv4TcpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR, 1609 dstPort, srcPort, ackNum, seqNum + 1, 0 /* dataLength */)); 1610 // Verify IPv4 non-keepalive ack packet from the same source address is passed 1611 assertPass(program, 1612 ipv4TcpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR, 1613 dstPort, srcPort, ackNum + 100, seqNum, 0 /* dataLength */)); 1614 assertPass(program, 1615 ipv4TcpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR, 1616 dstPort, srcPort, ackNum, seqNum + 1, 10 /* dataLength */)); 1617 // Verify IPv4 packet from another address is passed 1618 assertPass(program, 1619 ipv4TcpPacket(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR, anotherSrcPort, 1620 anotherDstPort, anotherSeqNum, anotherAckNum, 0 /* dataLength */)); 1621 1622 // Remove IPv4 keepalive filter 1623 apfFilter.removeKeepalivePacketFilter(slot1); 1624 1625 try { 1626 // src: 2404:0:0:0:0:0:faf1, port: 12345 1627 // dst: 2404:0:0:0:0:0:faf2, port: 54321 1628 srcAddr = InetAddress.getByAddress(IPV6_KEEPALIVE_SRC_ADDR); 1629 dstAddr = InetAddress.getByAddress(IPV6_KEEPALIVE_DST_ADDR); 1630 1631 final TcpKeepalivePacketDataParcelable ipv6Parcel = 1632 new TcpKeepalivePacketDataParcelable(); 1633 ipv6Parcel.srcAddress = srcAddr.getAddress(); 1634 ipv6Parcel.srcPort = srcPort; 1635 ipv6Parcel.dstAddress = dstAddr.getAddress(); 1636 ipv6Parcel.dstPort = dstPort; 1637 ipv6Parcel.seq = seqNum; 1638 ipv6Parcel.ack = ackNum; 1639 1640 apfFilter.addTcpKeepalivePacketFilter(slot1, ipv6Parcel); 1641 program = cb.getApfProgram(); 1642 1643 // Verify IPv6 keepalive ack packet is dropped 1644 // src: 2404:0:0:0:0:0:faf2, port: 54321 1645 // dst: 2404:0:0:0:0:0:faf1, port: 12345 1646 assertDrop(program, 1647 ipv6TcpPacket(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR, 1648 dstPort, srcPort, ackNum, seqNum + 1)); 1649 // Verify IPv6 non-keepalive ack packet from the same source address is passed 1650 assertPass(program, 1651 ipv6TcpPacket(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR, 1652 dstPort, srcPort, ackNum + 100, seqNum)); 1653 // Verify IPv6 packet from another address is passed 1654 assertPass(program, 1655 ipv6TcpPacket(IPV6_ANOTHER_ADDR, IPV6_KEEPALIVE_SRC_ADDR, anotherSrcPort, 1656 anotherDstPort, anotherSeqNum, anotherAckNum)); 1657 1658 // Remove IPv6 keepalive filter 1659 apfFilter.removeKeepalivePacketFilter(slot1); 1660 1661 // Verify multiple filters 1662 apfFilter.addTcpKeepalivePacketFilter(slot1, parcel); 1663 apfFilter.addTcpKeepalivePacketFilter(slot2, ipv6Parcel); 1664 program = cb.getApfProgram(); 1665 1666 // Verify IPv4 keepalive ack packet is dropped 1667 // src: 10.0.0.6, port: 54321 1668 // dst: 10.0.0.5, port: 12345 1669 assertDrop(program, 1670 ipv4TcpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR, 1671 dstPort, srcPort, ackNum, seqNum + 1, 0 /* dataLength */)); 1672 // Verify IPv4 non-keepalive ack packet from the same source address is passed 1673 assertPass(program, 1674 ipv4TcpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR, 1675 dstPort, srcPort, ackNum + 100, seqNum, 0 /* dataLength */)); 1676 // Verify IPv4 packet from another address is passed 1677 assertPass(program, 1678 ipv4TcpPacket(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR, anotherSrcPort, 1679 anotherDstPort, anotherSeqNum, anotherAckNum, 0 /* dataLength */)); 1680 1681 // Verify IPv6 keepalive ack packet is dropped 1682 // src: 2404:0:0:0:0:0:faf2, port: 54321 1683 // dst: 2404:0:0:0:0:0:faf1, port: 12345 1684 assertDrop(program, 1685 ipv6TcpPacket(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR, 1686 dstPort, srcPort, ackNum, seqNum + 1)); 1687 // Verify IPv6 non-keepalive ack packet from the same source address is passed 1688 assertPass(program, 1689 ipv6TcpPacket(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR, 1690 dstPort, srcPort, ackNum + 100, seqNum)); 1691 // Verify IPv6 packet from another address is passed 1692 assertPass(program, 1693 ipv6TcpPacket(IPV6_ANOTHER_ADDR, IPV6_KEEPALIVE_SRC_ADDR, anotherSrcPort, 1694 anotherDstPort, anotherSeqNum, anotherAckNum)); 1695 1696 // Remove keepalive filters 1697 apfFilter.removeKeepalivePacketFilter(slot1); 1698 apfFilter.removeKeepalivePacketFilter(slot2); 1699 } catch (UnsupportedOperationException e) { 1700 // TODO: support V6 packets 1701 } 1702 1703 program = cb.getApfProgram(); 1704 1705 // Verify IPv4, IPv6 packets are passed 1706 assertPass(program, 1707 ipv4TcpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR, 1708 dstPort, srcPort, ackNum, seqNum + 1, 0 /* dataLength */)); 1709 assertPass(program, 1710 ipv6TcpPacket(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR, 1711 dstPort, srcPort, ackNum, seqNum + 1)); 1712 assertPass(program, 1713 ipv4TcpPacket(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR, srcPort, 1714 dstPort, anotherSeqNum, anotherAckNum, 0 /* dataLength */)); 1715 assertPass(program, 1716 ipv6TcpPacket(IPV6_ANOTHER_ADDR, IPV6_KEEPALIVE_SRC_ADDR, srcPort, 1717 dstPort, anotherSeqNum, anotherAckNum)); 1718 1719 apfFilter.shutdown(); 1720 } 1721 ipv4TcpPacket(byte[] sip, byte[] dip, int sport, int dport, int seq, int ack, int dataLength)1722 private static byte[] ipv4TcpPacket(byte[] sip, byte[] dip, int sport, 1723 int dport, int seq, int ack, int dataLength) { 1724 final int totalLength = dataLength + IPV4_HEADER_LEN + IPV4_TCP_HEADER_LEN; 1725 1726 ByteBuffer packet = ByteBuffer.wrap(new byte[totalLength + ETH_HEADER_LEN]); 1727 1728 // Ethertype and IPv4 header 1729 setIpv4VersionFields(packet); 1730 packet.putShort(IPV4_TOTAL_LENGTH_OFFSET, (short) totalLength); 1731 packet.put(IPV4_PROTOCOL_OFFSET, (byte) IPPROTO_TCP); 1732 put(packet, IPV4_SRC_ADDR_OFFSET, sip); 1733 put(packet, IPV4_DEST_ADDR_OFFSET, dip); 1734 packet.putShort(IPV4_TCP_SRC_PORT_OFFSET, (short) sport); 1735 packet.putShort(IPV4_TCP_DEST_PORT_OFFSET, (short) dport); 1736 packet.putInt(IPV4_TCP_SEQ_NUM_OFFSET, seq); 1737 packet.putInt(IPV4_TCP_ACK_NUM_OFFSET, ack); 1738 1739 // TCP header length 5(20 bytes), reserved 3 bits, NS=0 1740 packet.put(IPV4_TCP_HEADER_LENGTH_OFFSET, (byte) 0x50); 1741 // TCP flags: ACK set 1742 packet.put(IPV4_TCP_HEADER_FLAG_OFFSET, (byte) 0x10); 1743 return packet.array(); 1744 } 1745 ipv6TcpPacket(byte[] sip, byte[] tip, int sport, int dport, int seq, int ack)1746 private static byte[] ipv6TcpPacket(byte[] sip, byte[] tip, int sport, 1747 int dport, int seq, int ack) { 1748 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1749 setIpv6VersionFields(packet); 1750 packet.put(IPV6_NEXT_HEADER_OFFSET, (byte) IPPROTO_TCP); 1751 put(packet, IPV6_SRC_ADDR_OFFSET, sip); 1752 put(packet, IPV6_DEST_ADDR_OFFSET, tip); 1753 packet.putShort(IPV6_TCP_SRC_PORT_OFFSET, (short) sport); 1754 packet.putShort(IPV6_TCP_DEST_PORT_OFFSET, (short) dport); 1755 packet.putInt(IPV6_TCP_SEQ_NUM_OFFSET, seq); 1756 packet.putInt(IPV6_TCP_ACK_NUM_OFFSET, ack); 1757 return packet.array(); 1758 } 1759 1760 @Test testApfFilterNattKeepalivePacket()1761 public void testApfFilterNattKeepalivePacket() throws Exception { 1762 final MockIpClientCallback cb = new MockIpClientCallback(); 1763 final ApfConfiguration config = getDefaultConfig(); 1764 config.multicastFilter = DROP_MULTICAST; 1765 config.ieee802_3Filter = DROP_802_3_FRAMES; 1766 final TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog); 1767 byte[] program; 1768 final int srcPort = 1024; 1769 final int dstPort = 4500; 1770 final int slot1 = 1; 1771 // NAT-T keepalive 1772 final byte[] kaPayload = {(byte) 0xff}; 1773 final byte[] nonKaPayload = {(byte) 0xfe}; 1774 1775 // src: 10.0.0.5, port: 1024 1776 // dst: 10.0.0.6, port: 4500 1777 InetAddress srcAddr = InetAddress.getByAddress(IPV4_KEEPALIVE_SRC_ADDR); 1778 InetAddress dstAddr = InetAddress.getByAddress(IPV4_KEEPALIVE_DST_ADDR); 1779 1780 final NattKeepalivePacketDataParcelable parcel = new NattKeepalivePacketDataParcelable(); 1781 parcel.srcAddress = srcAddr.getAddress(); 1782 parcel.srcPort = srcPort; 1783 parcel.dstAddress = dstAddr.getAddress(); 1784 parcel.dstPort = dstPort; 1785 1786 apfFilter.addNattKeepalivePacketFilter(slot1, parcel); 1787 program = cb.getApfProgram(); 1788 1789 // Verify IPv4 keepalive packet is dropped 1790 // src: 10.0.0.6, port: 4500 1791 // dst: 10.0.0.5, port: 1024 1792 byte[] pkt = ipv4UdpPacket(IPV4_KEEPALIVE_DST_ADDR, 1793 IPV4_KEEPALIVE_SRC_ADDR, dstPort, srcPort, 1 /* dataLength */); 1794 System.arraycopy(kaPayload, 0, pkt, IPV4_UDP_PAYLOAD_OFFSET, kaPayload.length); 1795 assertDrop(program, pkt); 1796 1797 // Verify a packet with payload length 1 byte but it is not 0xff will pass the filter. 1798 System.arraycopy(nonKaPayload, 0, pkt, IPV4_UDP_PAYLOAD_OFFSET, nonKaPayload.length); 1799 assertPass(program, pkt); 1800 1801 // Verify IPv4 non-keepalive response packet from the same source address is passed 1802 assertPass(program, 1803 ipv4UdpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR, 1804 dstPort, srcPort, 10 /* dataLength */)); 1805 1806 // Verify IPv4 non-keepalive response packet from other source address is passed 1807 assertPass(program, 1808 ipv4UdpPacket(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR, 1809 dstPort, srcPort, 10 /* dataLength */)); 1810 1811 apfFilter.removeKeepalivePacketFilter(slot1); 1812 apfFilter.shutdown(); 1813 } 1814 ipv4UdpPacket(byte[] sip, byte[] dip, int sport, int dport, int dataLength)1815 private static byte[] ipv4UdpPacket(byte[] sip, byte[] dip, int sport, 1816 int dport, int dataLength) { 1817 final int totalLength = dataLength + IPV4_HEADER_LEN + UDP_HEADER_LEN; 1818 final int udpLength = UDP_HEADER_LEN + dataLength; 1819 ByteBuffer packet = ByteBuffer.wrap(new byte[totalLength + ETH_HEADER_LEN]); 1820 1821 // Ethertype and IPv4 header 1822 setIpv4VersionFields(packet); 1823 packet.putShort(IPV4_TOTAL_LENGTH_OFFSET, (short) totalLength); 1824 packet.put(IPV4_PROTOCOL_OFFSET, (byte) IPPROTO_UDP); 1825 put(packet, IPV4_SRC_ADDR_OFFSET, sip); 1826 put(packet, IPV4_DEST_ADDR_OFFSET, dip); 1827 packet.putShort(IPV4_UDP_SRC_PORT_OFFSET, (short) sport); 1828 packet.putShort(IPV4_UDP_DEST_PORT_OFFSET, (short) dport); 1829 packet.putShort(IPV4_UDP_LENGTH_OFFSET, (short) udpLength); 1830 1831 return packet.array(); 1832 } 1833 addRdnssOption(ByteBuffer packet, int lifetime, String... servers)1834 private void addRdnssOption(ByteBuffer packet, int lifetime, String... servers) 1835 throws Exception { 1836 int optionLength = 1 + 2 * servers.length; // In 8-byte units 1837 packet.put((byte) ICMP6_RDNSS_OPTION_TYPE); // Type 1838 packet.put((byte) optionLength); // Length 1839 packet.putShort((short) 0); // Reserved 1840 packet.putInt(lifetime); // Lifetime 1841 for (String server : servers) { 1842 packet.put(InetAddress.getByName(server).getAddress()); 1843 } 1844 } 1845 addRioOption(ByteBuffer packet, int lifetime, String prefixString)1846 private void addRioOption(ByteBuffer packet, int lifetime, String prefixString) 1847 throws Exception { 1848 IpPrefix prefix = new IpPrefix(prefixString); 1849 1850 int optionLength; 1851 if (prefix.getPrefixLength() == 0) { 1852 optionLength = 1; 1853 } else if (prefix.getPrefixLength() <= 64) { 1854 optionLength = 2; 1855 } else { 1856 optionLength = 3; 1857 } 1858 1859 packet.put((byte) ICMP6_ROUTE_INFO_OPTION_TYPE); // Type 1860 packet.put((byte) optionLength); // Length in 8-byte units 1861 packet.put((byte) prefix.getPrefixLength()); // Prefix length 1862 packet.put((byte) 0b00011000); // Pref = high 1863 packet.putInt(lifetime); // Lifetime 1864 1865 byte[] prefixBytes = prefix.getRawAddress(); 1866 packet.put(prefixBytes, 0, (optionLength - 1) * 8); 1867 } 1868 addPioOption(ByteBuffer packet, int valid, int preferred, String prefixString)1869 private void addPioOption(ByteBuffer packet, int valid, int preferred, String prefixString) { 1870 IpPrefix prefix = new IpPrefix(prefixString); 1871 packet.put((byte) ICMP6_PREFIX_OPTION_TYPE); // Type 1872 packet.put((byte) 4); // Length in 8-byte units 1873 packet.put((byte) prefix.getPrefixLength()); // Prefix length 1874 packet.put((byte) 0b11000000); // L = 1, A = 1 1875 packet.putInt(valid); 1876 packet.putInt(preferred); 1877 packet.putInt(0); // Reserved 1878 packet.put(prefix.getRawAddress()); 1879 } 1880 buildLargeRa()1881 private byte[] buildLargeRa() throws Exception { 1882 InetAddress src = InetAddress.getByName("fe80::1234:abcd"); 1883 1884 ByteBuffer packet = ByteBuffer.wrap(new byte[1514]); 1885 packet.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IPV6); 1886 packet.position(ETH_HEADER_LEN); 1887 1888 packet.putInt(0x60012345); // Version, tclass, flowlabel 1889 packet.putShort((short) 0); // Payload length; updated later 1890 packet.put((byte) IPPROTO_ICMPV6); // Next header 1891 packet.put((byte) 0xff); // Hop limit 1892 packet.put(src.getAddress()); // Source address 1893 packet.put(IPV6_ALL_NODES_ADDRESS); // Destination address 1894 1895 packet.put((byte) ICMP6_ROUTER_ADVERTISEMENT); // Type 1896 packet.put((byte) 0); // Code (0) 1897 packet.putShort((short) 0); // Checksum (ignored) 1898 packet.put((byte) 64); // Hop limit 1899 packet.put((byte) 0); // M/O, reserved 1900 packet.putShort((short) 1800); // Router lifetime 1901 packet.putInt(30_000); // Reachable time 1902 packet.putInt(1000); // Retrans timer 1903 1904 addRioOption(packet, 1200, "64:ff9b::/96"); 1905 addRdnssOption(packet, 7200, "2001:db8:1::1", "2001:db8:1::2"); 1906 addRioOption(packet, 2100, "2000::/3"); 1907 addRioOption(packet, 2400, "::/0"); 1908 addPioOption(packet, 600, 300, "2001:db8:a::/64"); 1909 addRioOption(packet, 1500, "2001:db8:c:d::/64"); 1910 addPioOption(packet, 86400, 43200, "fd95:d1e:12::/64"); 1911 1912 int length = packet.position(); 1913 packet.putShort(IPV6_PAYLOAD_LENGTH_OFFSET, (short) length); 1914 1915 // Don't pass the Ra constructor a packet that is longer than the actual RA. 1916 // This relies on the fact that all the relative writes to the byte buffer are at the end. 1917 byte[] packetArray = new byte[length]; 1918 packet.rewind(); 1919 packet.get(packetArray); 1920 return packetArray; 1921 } 1922 1923 @Test testRaToString()1924 public void testRaToString() throws Exception { 1925 MockIpClientCallback cb = new MockIpClientCallback(); 1926 ApfConfiguration config = getDefaultConfig(); 1927 TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog); 1928 1929 byte[] packet = buildLargeRa(); 1930 ApfFilter.Ra ra = apfFilter.new Ra(packet, packet.length); 1931 String expected = "RA fe80::1234:abcd -> ff02::1 1800s " 1932 + "2001:db8:a::/64 600s/300s fd95:d1e:12::/64 86400s/43200s " 1933 + "DNS 7200s 2001:db8:1::1 2001:db8:1::2 " 1934 + "RIO 1200s 64:ff9b::/96 RIO 2100s 2000::/3 " 1935 + "RIO 2400s ::/0 RIO 1500s 2001:db8:c:d::/64 "; 1936 assertEquals(expected, ra.toString()); 1937 } 1938 1939 // Verify that the last program pushed to the IpClient.Callback properly filters the 1940 // given packet for the given lifetime. verifyRaLifetime(byte[] program, ByteBuffer packet, int lifetime)1941 private void verifyRaLifetime(byte[] program, ByteBuffer packet, int lifetime) { 1942 final int FRACTION_OF_LIFETIME = 6; 1943 final int ageLimit = lifetime / FRACTION_OF_LIFETIME; 1944 1945 // Verify new program should drop RA for 1/6th its lifetime and pass afterwards. 1946 assertDrop(program, packet.array()); 1947 assertDrop(program, packet.array(), ageLimit); 1948 assertPass(program, packet.array(), ageLimit + 1); 1949 assertPass(program, packet.array(), lifetime); 1950 // Verify RA checksum is ignored 1951 final short originalChecksum = packet.getShort(ICMP6_RA_CHECKSUM_OFFSET); 1952 packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)12345); 1953 assertDrop(program, packet.array()); 1954 packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)-12345); 1955 assertDrop(program, packet.array()); 1956 packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, originalChecksum); 1957 1958 // Verify other changes to RA (e.g., a change in the source address) make it not match. 1959 final int offset = IPV6_SRC_ADDR_OFFSET + 5; 1960 final byte originalByte = packet.get(offset); 1961 packet.put(offset, (byte) (~originalByte)); 1962 assertPass(program, packet.array()); 1963 packet.put(offset, originalByte); 1964 assertDrop(program, packet.array()); 1965 } 1966 1967 // Test that when ApfFilter is shown the given packet, it generates a program to filter it 1968 // for the given lifetime. verifyRaLifetime(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback, ByteBuffer packet, int lifetime)1969 private void verifyRaLifetime(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback, 1970 ByteBuffer packet, int lifetime) throws IOException, ErrnoException { 1971 // Verify new program generated if ApfFilter witnesses RA 1972 ipClientCallback.resetApfProgramWait(); 1973 apfFilter.pretendPacketReceived(packet.array()); 1974 byte[] program = ipClientCallback.getApfProgram(); 1975 verifyRaLifetime(program, packet, lifetime); 1976 } 1977 verifyRaEvent(RaEvent expected)1978 private void verifyRaEvent(RaEvent expected) { 1979 ArgumentCaptor<IpConnectivityLog.Event> captor = 1980 ArgumentCaptor.forClass(IpConnectivityLog.Event.class); 1981 verify(mLog, atLeastOnce()).log(captor.capture()); 1982 RaEvent got = lastRaEvent(captor.getAllValues()); 1983 if (!raEventEquals(expected, got)) { 1984 assertEquals(expected, got); // fail for printing an assertion error message. 1985 } 1986 } 1987 lastRaEvent(List<IpConnectivityLog.Event> events)1988 private RaEvent lastRaEvent(List<IpConnectivityLog.Event> events) { 1989 RaEvent got = null; 1990 for (Parcelable ev : events) { 1991 if (ev instanceof RaEvent) { 1992 got = (RaEvent) ev; 1993 } 1994 } 1995 return got; 1996 } 1997 raEventEquals(RaEvent ev1, RaEvent ev2)1998 private boolean raEventEquals(RaEvent ev1, RaEvent ev2) { 1999 return (ev1 != null) && (ev2 != null) 2000 && (ev1.routerLifetime == ev2.routerLifetime) 2001 && (ev1.prefixValidLifetime == ev2.prefixValidLifetime) 2002 && (ev1.prefixPreferredLifetime == ev2.prefixPreferredLifetime) 2003 && (ev1.routeInfoLifetime == ev2.routeInfoLifetime) 2004 && (ev1.rdnssLifetime == ev2.rdnssLifetime) 2005 && (ev1.dnsslLifetime == ev2.dnsslLifetime); 2006 } 2007 assertInvalidRa(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback, ByteBuffer packet)2008 private void assertInvalidRa(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback, 2009 ByteBuffer packet) throws IOException, ErrnoException { 2010 ipClientCallback.resetApfProgramWait(); 2011 apfFilter.pretendPacketReceived(packet.array()); 2012 ipClientCallback.assertNoProgramUpdate(); 2013 } 2014 makeBaseRaPacket()2015 private ByteBuffer makeBaseRaPacket() { 2016 ByteBuffer basePacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]); 2017 final int ROUTER_LIFETIME = 1000; 2018 final int VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET = ETH_HEADER_LEN; 2019 // IPv6, traffic class = 0, flow label = 0x12345 2020 final int VERSION_TRAFFIC_CLASS_FLOW_LABEL = 0x60012345; 2021 2022 basePacket.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IPV6); 2023 basePacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET, 2024 VERSION_TRAFFIC_CLASS_FLOW_LABEL); 2025 basePacket.put(IPV6_NEXT_HEADER_OFFSET, (byte) IPPROTO_ICMPV6); 2026 basePacket.put(ICMP6_TYPE_OFFSET, (byte) ICMP6_ROUTER_ADVERTISEMENT); 2027 basePacket.putShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET, (short) ROUTER_LIFETIME); 2028 basePacket.position(IPV6_DEST_ADDR_OFFSET); 2029 basePacket.put(IPV6_ALL_NODES_ADDRESS); 2030 2031 return basePacket; 2032 } 2033 2034 @Test testApfFilterRa()2035 public void testApfFilterRa() throws Exception { 2036 MockIpClientCallback ipClientCallback = new MockIpClientCallback(); 2037 ApfConfiguration config = getDefaultConfig(); 2038 config.multicastFilter = DROP_MULTICAST; 2039 config.ieee802_3Filter = DROP_802_3_FRAMES; 2040 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog); 2041 byte[] program = ipClientCallback.getApfProgram(); 2042 2043 final int ROUTER_LIFETIME = 1000; 2044 final int PREFIX_VALID_LIFETIME = 200; 2045 final int PREFIX_PREFERRED_LIFETIME = 100; 2046 final int RDNSS_LIFETIME = 300; 2047 final int ROUTE_LIFETIME = 400; 2048 // Note that lifetime of 2000 will be ignored in favor of shorter route lifetime of 1000. 2049 final int DNSSL_LIFETIME = 2000; 2050 final int VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET = ETH_HEADER_LEN; 2051 // IPv6, traffic class = 0, flow label = 0x12345 2052 final int VERSION_TRAFFIC_CLASS_FLOW_LABEL = 0x60012345; 2053 2054 // Verify RA is passed the first time 2055 ByteBuffer basePacket = makeBaseRaPacket(); 2056 assertPass(program, basePacket.array()); 2057 2058 verifyRaLifetime(apfFilter, ipClientCallback, basePacket, ROUTER_LIFETIME); 2059 verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, -1)); 2060 2061 ByteBuffer newFlowLabelPacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]); 2062 basePacket.clear(); 2063 newFlowLabelPacket.put(basePacket); 2064 // Check that changes are ignored in every byte of the flow label. 2065 newFlowLabelPacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET, 2066 VERSION_TRAFFIC_CLASS_FLOW_LABEL + 0x11111); 2067 2068 // Ensure zero-length options cause the packet to be silently skipped. 2069 // Do this before we test other packets. http://b/29586253 2070 ByteBuffer zeroLengthOptionPacket = ByteBuffer.wrap( 2071 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]); 2072 basePacket.clear(); 2073 zeroLengthOptionPacket.put(basePacket); 2074 zeroLengthOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE); 2075 zeroLengthOptionPacket.put((byte)0); 2076 assertInvalidRa(apfFilter, ipClientCallback, zeroLengthOptionPacket); 2077 2078 // Generate several RAs with different options and lifetimes, and verify when 2079 // ApfFilter is shown these packets, it generates programs to filter them for the 2080 // appropriate lifetime. 2081 ByteBuffer prefixOptionPacket = ByteBuffer.wrap( 2082 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_LEN]); 2083 basePacket.clear(); 2084 prefixOptionPacket.put(basePacket); 2085 addPioOption(prefixOptionPacket, PREFIX_VALID_LIFETIME, PREFIX_PREFERRED_LIFETIME, 2086 "2001:db8::/64"); 2087 verifyRaLifetime( 2088 apfFilter, ipClientCallback, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME); 2089 verifyRaEvent(new RaEvent( 2090 ROUTER_LIFETIME, PREFIX_VALID_LIFETIME, PREFIX_PREFERRED_LIFETIME, -1, -1, -1)); 2091 2092 ByteBuffer rdnssOptionPacket = ByteBuffer.wrap( 2093 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN + 2 * IPV6_ADDR_LEN]); 2094 basePacket.clear(); 2095 rdnssOptionPacket.put(basePacket); 2096 addRdnssOption(rdnssOptionPacket, RDNSS_LIFETIME, 2097 "2001:4860:4860::8888", "2001:4860:4860::8844"); 2098 verifyRaLifetime(apfFilter, ipClientCallback, rdnssOptionPacket, RDNSS_LIFETIME); 2099 verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, RDNSS_LIFETIME, -1)); 2100 2101 final int lowLifetime = 60; 2102 ByteBuffer lowLifetimeRdnssOptionPacket = ByteBuffer.wrap( 2103 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN + IPV6_ADDR_LEN]); 2104 basePacket.clear(); 2105 lowLifetimeRdnssOptionPacket.put(basePacket); 2106 addRdnssOption(lowLifetimeRdnssOptionPacket, lowLifetime, "2620:fe::9"); 2107 verifyRaLifetime(apfFilter, ipClientCallback, lowLifetimeRdnssOptionPacket, 2108 ROUTER_LIFETIME); 2109 verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, lowLifetime, -1)); 2110 2111 ByteBuffer routeInfoOptionPacket = ByteBuffer.wrap( 2112 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN + IPV6_ADDR_LEN]); 2113 basePacket.clear(); 2114 routeInfoOptionPacket.put(basePacket); 2115 addRioOption(routeInfoOptionPacket, ROUTE_LIFETIME, "64:ff9b::/96"); 2116 verifyRaLifetime(apfFilter, ipClientCallback, routeInfoOptionPacket, ROUTE_LIFETIME); 2117 verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, ROUTE_LIFETIME, -1, -1)); 2118 2119 // Check that RIOs differing only in the first 4 bytes are different. 2120 ByteBuffer similarRouteInfoOptionPacket = ByteBuffer.wrap( 2121 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN + IPV6_ADDR_LEN]); 2122 basePacket.clear(); 2123 similarRouteInfoOptionPacket.put(basePacket); 2124 addRioOption(similarRouteInfoOptionPacket, ROUTE_LIFETIME, "64:ff9b::/64"); 2125 // Packet should be passed because it is different. 2126 program = ipClientCallback.getApfProgram(); 2127 assertPass(program, similarRouteInfoOptionPacket.array()); 2128 2129 ByteBuffer dnsslOptionPacket = ByteBuffer.wrap( 2130 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]); 2131 basePacket.clear(); 2132 dnsslOptionPacket.put(basePacket); 2133 dnsslOptionPacket.put((byte)ICMP6_DNSSL_OPTION_TYPE); 2134 dnsslOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8)); 2135 dnsslOptionPacket.putInt( 2136 ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, DNSSL_LIFETIME); 2137 verifyRaLifetime(apfFilter, ipClientCallback, dnsslOptionPacket, ROUTER_LIFETIME); 2138 verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, DNSSL_LIFETIME)); 2139 2140 ByteBuffer largeRaPacket = ByteBuffer.wrap(buildLargeRa()); 2141 verifyRaLifetime(apfFilter, ipClientCallback, largeRaPacket, 300); 2142 verifyRaEvent(new RaEvent(1800, 600, 300, 1200, 7200, -1)); 2143 2144 // Verify that current program filters all the RAs (note: ApfFilter.MAX_RAS == 10). 2145 program = ipClientCallback.getApfProgram(); 2146 verifyRaLifetime(program, basePacket, ROUTER_LIFETIME); 2147 verifyRaLifetime(program, newFlowLabelPacket, ROUTER_LIFETIME); 2148 verifyRaLifetime(program, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME); 2149 verifyRaLifetime(program, rdnssOptionPacket, RDNSS_LIFETIME); 2150 verifyRaLifetime(program, lowLifetimeRdnssOptionPacket, ROUTER_LIFETIME); 2151 verifyRaLifetime(program, routeInfoOptionPacket, ROUTE_LIFETIME); 2152 verifyRaLifetime(program, dnsslOptionPacket, ROUTER_LIFETIME); 2153 verifyRaLifetime(program, largeRaPacket, 300); 2154 2155 apfFilter.shutdown(); 2156 } 2157 2158 @Test testRaWithDifferentReachableTimeAndRetransTimer()2159 public void testRaWithDifferentReachableTimeAndRetransTimer() throws Exception { 2160 final MockIpClientCallback ipClientCallback = new MockIpClientCallback(); 2161 final ApfConfiguration config = getDefaultConfig(); 2162 config.multicastFilter = DROP_MULTICAST; 2163 config.ieee802_3Filter = DROP_802_3_FRAMES; 2164 final TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog); 2165 byte[] program = ipClientCallback.getApfProgram(); 2166 final int RA_REACHABLE_TIME = 1800; 2167 final int RA_RETRANSMISSION_TIMER = 1234; 2168 2169 // Create an Ra packet without options 2170 // Reachable time = 1800, retransmission timer = 1234 2171 ByteBuffer raPacket = makeBaseRaPacket(); 2172 raPacket.position(ICMP6_RA_REACHABLE_TIME_OFFSET); 2173 raPacket.putInt(RA_REACHABLE_TIME); 2174 raPacket.putInt(RA_RETRANSMISSION_TIMER); 2175 // First RA passes filter 2176 assertPass(program, raPacket.array()); 2177 2178 // Assume apf is shown the given RA, it generates program to filter it. 2179 ipClientCallback.resetApfProgramWait(); 2180 apfFilter.pretendPacketReceived(raPacket.array()); 2181 program = ipClientCallback.getApfProgram(); 2182 assertDrop(program, raPacket.array()); 2183 2184 // A packet with different reachable time should be passed. 2185 // Reachable time = 2300, retransmission timer = 1234 2186 raPacket.clear(); 2187 raPacket.putInt(ICMP6_RA_REACHABLE_TIME_OFFSET, RA_REACHABLE_TIME + 500); 2188 assertPass(program, raPacket.array()); 2189 2190 // A packet with different retransmission timer should be passed. 2191 // Reachable time = 1800, retransmission timer = 2234 2192 raPacket.clear(); 2193 raPacket.putInt(ICMP6_RA_REACHABLE_TIME_OFFSET, RA_REACHABLE_TIME); 2194 raPacket.putInt(ICMP6_RA_RETRANSMISSION_TIMER_OFFSET, RA_RETRANSMISSION_TIMER + 1000); 2195 assertPass(program, raPacket.array()); 2196 } 2197 2198 /** 2199 * Stage a file for testing, i.e. make it native accessible. Given a resource ID, 2200 * copy that resource into the app's data directory and return the path to it. 2201 */ stageFile(int rawId)2202 private String stageFile(int rawId) throws Exception { 2203 File file = new File(InstrumentationRegistry.getContext().getFilesDir(), "staged_file"); 2204 new File(file.getParent()).mkdirs(); 2205 InputStream in = null; 2206 OutputStream out = null; 2207 try { 2208 in = InstrumentationRegistry.getContext().getResources().openRawResource(rawId); 2209 out = new FileOutputStream(file); 2210 Streams.copy(in, out); 2211 } finally { 2212 if (in != null) in.close(); 2213 if (out != null) out.close(); 2214 } 2215 return file.getAbsolutePath(); 2216 } 2217 put(ByteBuffer buffer, int position, byte[] bytes)2218 private static void put(ByteBuffer buffer, int position, byte[] bytes) { 2219 final int original = buffer.position(); 2220 buffer.position(position); 2221 buffer.put(bytes); 2222 buffer.position(original); 2223 } 2224 2225 @Test testRaParsing()2226 public void testRaParsing() throws Exception { 2227 final int maxRandomPacketSize = 512; 2228 final Random r = new Random(); 2229 MockIpClientCallback cb = new MockIpClientCallback(); 2230 ApfConfiguration config = getDefaultConfig(); 2231 config.multicastFilter = DROP_MULTICAST; 2232 config.ieee802_3Filter = DROP_802_3_FRAMES; 2233 TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog); 2234 for (int i = 0; i < 1000; i++) { 2235 byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)]; 2236 r.nextBytes(packet); 2237 try { 2238 apfFilter.new Ra(packet, packet.length); 2239 } catch (ApfFilter.InvalidRaException e) { 2240 } catch (Exception e) { 2241 throw new Exception("bad packet: " + HexDump.toHexString(packet), e); 2242 } 2243 } 2244 } 2245 2246 @Test testRaProcessing()2247 public void testRaProcessing() throws Exception { 2248 final int maxRandomPacketSize = 512; 2249 final Random r = new Random(); 2250 MockIpClientCallback cb = new MockIpClientCallback(); 2251 ApfConfiguration config = getDefaultConfig(); 2252 config.multicastFilter = DROP_MULTICAST; 2253 config.ieee802_3Filter = DROP_802_3_FRAMES; 2254 TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog); 2255 for (int i = 0; i < 1000; i++) { 2256 byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)]; 2257 r.nextBytes(packet); 2258 try { 2259 apfFilter.processRa(packet, packet.length); 2260 } catch (Exception e) { 2261 throw new Exception("bad packet: " + HexDump.toHexString(packet), e); 2262 } 2263 } 2264 } 2265 2266 /** 2267 * Call the APF interpreter to run {@code program} on {@code packet} with persistent memory 2268 * segment {@data} pretending the filter was installed {@code filter_age} seconds ago. 2269 */ apfSimulate(byte[] program, byte[] packet, byte[] data, int filter_age)2270 private native static int apfSimulate(byte[] program, byte[] packet, byte[] data, 2271 int filter_age); 2272 2273 /** 2274 * Compile a tcpdump human-readable filter (e.g. "icmp" or "tcp port 54") into a BPF 2275 * prorgam and return a human-readable dump of the BPF program identical to "tcpdump -d". 2276 */ compileToBpf(String filter)2277 private native static String compileToBpf(String filter); 2278 2279 /** 2280 * Open packet capture file {@code pcap_filename} and filter the packets using tcpdump 2281 * human-readable filter (e.g. "icmp" or "tcp port 54") compiled to a BPF program and 2282 * at the same time using APF program {@code apf_program}. Return {@code true} if 2283 * both APF and BPF programs filter out exactly the same packets. 2284 */ compareBpfApf(String filter, String pcap_filename, byte[] apf_program)2285 private native static boolean compareBpfApf(String filter, String pcap_filename, 2286 byte[] apf_program); 2287 2288 2289 /** 2290 * Open packet capture file {@code pcapFilename} and run it through APF filter. Then 2291 * checks whether all the packets are dropped and populates data[] {@code data} with 2292 * the APF counters. 2293 */ dropsAllPackets(byte[] program, byte[] data, String pcapFilename)2294 private native static boolean dropsAllPackets(byte[] program, byte[] data, String pcapFilename); 2295 2296 @Test testBroadcastAddress()2297 public void testBroadcastAddress() throws Exception { 2298 assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 0)); 2299 assertEqualsIp("0.0.0.0", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 32)); 2300 assertEqualsIp("0.0.3.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 22)); 2301 assertEqualsIp("0.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 8)); 2302 2303 assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 0)); 2304 assertEqualsIp("10.0.0.1", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 32)); 2305 assertEqualsIp("10.0.0.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 24)); 2306 assertEqualsIp("10.0.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 16)); 2307 } 2308 assertEqualsIp(String expected, int got)2309 public void assertEqualsIp(String expected, int got) throws Exception { 2310 int want = Inet4AddressUtils.inet4AddressToIntHTH( 2311 (Inet4Address) InetAddresses.parseNumericAddress(expected)); 2312 assertEquals(want, got); 2313 } 2314 } 2315