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