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