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.net.apf.ApfCounterTracker.Counter.getCounterEnumFromOffset; 20 import static android.net.apf.ApfTestHelpers.TIMEOUT_MS; 21 import static android.net.apf.ApfTestHelpers.DROP; 22 import static android.net.apf.ApfTestHelpers.MIN_PKT_SIZE; 23 import static android.net.apf.ApfTestHelpers.PASS; 24 import static android.net.apf.ApfTestHelpers.assertProgramEquals; 25 import static android.net.apf.BaseApfGenerator.APF_VERSION_3; 26 import static android.net.apf.BaseApfGenerator.APF_VERSION_4; 27 import static android.net.apf.BaseApfGenerator.APF_VERSION_6; 28 import static android.net.apf.BaseApfGenerator.DROP_LABEL; 29 import static android.net.apf.BaseApfGenerator.MemorySlot; 30 import static android.net.apf.BaseApfGenerator.PASS_LABEL; 31 import static android.net.apf.BaseApfGenerator.Register.R0; 32 import static android.net.apf.BaseApfGenerator.Register.R1; 33 import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED; 34 import static android.os.PowerManager.ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED; 35 import static android.system.OsConstants.AF_UNIX; 36 import static android.system.OsConstants.ETH_P_ARP; 37 import static android.system.OsConstants.ETH_P_IP; 38 import static android.system.OsConstants.ETH_P_IPV6; 39 import static android.system.OsConstants.IPPROTO_ICMPV6; 40 import static android.system.OsConstants.IPPROTO_IPV6; 41 import static android.system.OsConstants.IPPROTO_UDP; 42 import static android.system.OsConstants.SOCK_STREAM; 43 44 import static com.android.net.module.util.HexDump.hexStringToByteArray; 45 import static com.android.net.module.util.HexDump.toHexString; 46 import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ECHO_REQUEST_TYPE; 47 48 import static org.junit.Assert.assertEquals; 49 import static org.junit.Assert.assertTrue; 50 import static org.junit.Assert.fail; 51 import static org.mockito.ArgumentMatchers.anyInt; 52 import static org.mockito.Mockito.any; 53 import static org.mockito.Mockito.clearInvocations; 54 import static org.mockito.Mockito.doAnswer; 55 import static org.mockito.Mockito.doReturn; 56 import static org.mockito.Mockito.never; 57 import static org.mockito.Mockito.reset; 58 import static org.mockito.Mockito.times; 59 import static org.mockito.Mockito.verify; 60 61 import android.content.BroadcastReceiver; 62 import android.content.Context; 63 import android.content.Intent; 64 import android.net.InetAddresses; 65 import android.net.IpPrefix; 66 import android.net.LinkAddress; 67 import android.net.LinkProperties; 68 import android.net.MacAddress; 69 import android.net.apf.ApfCounterTracker.Counter; 70 import android.net.apf.ApfFilter.ApfConfiguration; 71 import android.net.apf.BaseApfGenerator.IllegalInstructionException; 72 import android.net.metrics.IpConnectivityLog; 73 import android.os.Build; 74 import android.os.Handler; 75 import android.os.HandlerThread; 76 import android.os.PowerManager; 77 import android.os.SystemClock; 78 import android.stats.connectivity.NetworkQuirkEvent; 79 import android.system.ErrnoException; 80 import android.system.Os; 81 import android.text.TextUtils; 82 import android.text.format.DateUtils; 83 import android.util.ArrayMap; 84 import android.util.Log; 85 import android.util.Pair; 86 87 import androidx.test.InstrumentationRegistry; 88 import androidx.test.filters.SmallTest; 89 90 import com.android.internal.annotations.GuardedBy; 91 import com.android.internal.util.HexDump; 92 import com.android.modules.utils.build.SdkLevel; 93 import com.android.net.module.util.DnsPacket; 94 import com.android.net.module.util.Inet4AddressUtils; 95 import com.android.net.module.util.InterfaceParams; 96 import com.android.net.module.util.NetworkStackConstants; 97 import com.android.net.module.util.PacketBuilder; 98 import com.android.networkstack.metrics.ApfSessionInfoMetrics; 99 import com.android.networkstack.metrics.IpClientRaInfoMetrics; 100 import com.android.networkstack.metrics.NetworkQuirkMetrics; 101 import com.android.server.networkstack.tests.R; 102 import com.android.testutils.ConcurrentUtils; 103 import com.android.testutils.DevSdkIgnoreRule; 104 import com.android.testutils.DevSdkIgnoreRunner; 105 import com.android.testutils.HandlerUtils; 106 107 import libcore.io.IoUtils; 108 import libcore.io.Streams; 109 110 import org.junit.After; 111 import org.junit.Before; 112 import org.junit.Rule; 113 import org.junit.Test; 114 import org.junit.runner.RunWith; 115 import org.junit.runners.Parameterized; 116 import org.mockito.ArgumentCaptor; 117 import org.mockito.Mock; 118 import org.mockito.Mockito; 119 import org.mockito.MockitoAnnotations; 120 121 import java.io.ByteArrayOutputStream; 122 import java.io.File; 123 import java.io.FileDescriptor; 124 import java.io.FileOutputStream; 125 import java.io.IOException; 126 import java.io.InputStream; 127 import java.io.InterruptedIOException; 128 import java.io.OutputStream; 129 import java.net.Inet4Address; 130 import java.net.Inet6Address; 131 import java.net.InetAddress; 132 import java.nio.ByteBuffer; 133 import java.nio.charset.StandardCharsets; 134 import java.util.ArrayList; 135 import java.util.Arrays; 136 import java.util.HashMap; 137 import java.util.List; 138 import java.util.Map; 139 import java.util.Random; 140 import java.util.concurrent.atomic.AtomicReference; 141 142 /** 143 * Tests for APF program generator and interpreter. 144 * 145 * The test cases will be executed by both APFv4 and APFv6 interpreter. 146 */ 147 @DevSdkIgnoreRunner.MonitorThreadLeak 148 @RunWith(DevSdkIgnoreRunner.class) 149 @SmallTest 150 public class ApfTest { 151 private static final int APF_VERSION_2 = 2; 152 private int mRamSize = 1024; 153 private int mClampSize = 1024; 154 155 @Rule 156 public DevSdkIgnoreRule mDevSdkIgnoreRule = new DevSdkIgnoreRule(); 157 // Indicates which apf interpreter to run. 158 @Parameterized.Parameter() 159 public int mApfVersion; 160 161 @Parameterized.Parameters data()162 public static Iterable<? extends Object> data() { 163 return Arrays.asList(4, 6); 164 } 165 166 @Mock private Context mContext; 167 @Mock 168 private ApfFilter.Dependencies mDependencies; 169 @Mock private PowerManager mPowerManager; 170 @Mock private IpConnectivityLog mIpConnectivityLog; 171 @Mock private NetworkQuirkMetrics mNetworkQuirkMetrics; 172 @Mock private ApfSessionInfoMetrics mApfSessionInfoMetrics; 173 @Mock private IpClientRaInfoMetrics mIpClientRaInfoMetrics; 174 @Mock private ApfFilter.IApfController mApfController; 175 @GuardedBy("mApfFilterCreated") 176 private final ArrayList<ApfFilter> mApfFilterCreated = new ArrayList<>(); 177 private FileDescriptor mWriteSocket; 178 private HandlerThread mHandlerThread; 179 private Handler mHandler; 180 private long mCurrentTimeMs; 181 private ApfTestHelpers mApfTestHelpers; 182 183 @Before setUp()184 public void setUp() throws Exception { 185 MockitoAnnotations.initMocks(this); 186 doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class); 187 doReturn(mApfSessionInfoMetrics).when(mDependencies).getApfSessionInfoMetrics(); 188 doReturn(mIpClientRaInfoMetrics).when(mDependencies).getIpClientRaInfoMetrics(); 189 FileDescriptor readSocket = new FileDescriptor(); 190 mWriteSocket = new FileDescriptor(); 191 Os.socketpair(AF_UNIX, SOCK_STREAM, 0, mWriteSocket, readSocket); 192 doReturn(readSocket).when(mDependencies).createPacketReaderSocket(anyInt()); 193 mCurrentTimeMs = SystemClock.elapsedRealtime(); 194 doReturn(mCurrentTimeMs).when(mDependencies).elapsedRealtime(); 195 doReturn(true).when(mApfController).installPacketFilter(any(), any()); 196 doAnswer((invocation) -> { 197 synchronized (mApfFilterCreated) { 198 mApfFilterCreated.add(invocation.getArgument(0)); 199 } 200 return null; 201 }).when(mDependencies).onApfFilterCreated(any()); 202 mHandlerThread = new HandlerThread("ApfTestThread"); 203 mHandlerThread.start(); 204 mHandler = new Handler(mHandlerThread.getLooper()); 205 mApfTestHelpers = new ApfTestHelpers(ApfJniUtils.APF_INTERPRETER_VERSION_V6); 206 } 207 shutdownApfFilters()208 private void shutdownApfFilters() throws Exception { 209 ConcurrentUtils.quitResources(THREAD_QUIT_MAX_RETRY_COUNT, () -> { 210 synchronized (mApfFilterCreated) { 211 final ArrayList<ApfFilter> ret = 212 new ArrayList<>(mApfFilterCreated); 213 mApfFilterCreated.clear(); 214 return ret; 215 } 216 }, (apf) -> mHandler.post(apf::shutdown)); 217 synchronized (mApfFilterCreated) { 218 assertEquals("ApfFilters did not fully shutdown.", 219 0, mApfFilterCreated.size()); 220 } 221 } 222 223 @After tearDown()224 public void tearDown() throws Exception { 225 IoUtils.closeQuietly(mWriteSocket); 226 shutdownApfFilters(); 227 HandlerUtils.waitForIdle(mHandler, TIMEOUT_MS); 228 // Clear mocks to prevent from stubs holding instances and cause memory leaks. 229 Mockito.framework().clearInlineMocks(); 230 mHandlerThread.quitSafely(); 231 mHandlerThread.join(); 232 } 233 234 private static final String TAG = "ApfTest"; 235 // Expected return codes from APF interpreter. 236 237 private static final boolean DROP_MULTICAST = true; 238 private static final boolean ALLOW_MULTICAST = false; 239 240 private static final boolean DROP_802_3_FRAMES = true; 241 private static final boolean ALLOW_802_3_FRAMES = false; 242 243 private static final int MIN_RDNSS_LIFETIME_SEC = 0; 244 private static final int MIN_METRICS_SESSION_DURATIONS_MS = 300_000; 245 246 private static final int NO_CALLBACK_TIMEOUT_MS = 500; 247 private static final int THREAD_QUIT_MAX_RETRY_COUNT = 3; 248 249 // Constants for opcode encoding 250 private static final byte LI_OP = (byte)(13 << 3); 251 private static final byte LDDW_OP = (byte)(22 << 3); 252 private static final byte STDW_OP = (byte)(23 << 3); 253 private static final byte SIZE0 = (byte)(0 << 1); 254 private static final byte SIZE8 = (byte)(1 << 1); 255 private static final byte SIZE16 = (byte)(2 << 1); 256 private static final byte SIZE32 = (byte)(3 << 1); 257 private static final byte R1_REG = 1; 258 259 private static final byte[] TEST_MAC_ADDR = {2, 3, 4, 5, 6, 7}; 260 private static final int TEST_IFACE_IDX = 1234; 261 private static final InterfaceParams TEST_PARAMS = new InterfaceParams("lo", TEST_IFACE_IDX, 262 MacAddress.fromBytes(TEST_MAC_ADDR), 1500 /* defaultMtu */); 263 getDefaultConfig()264 private static ApfConfiguration getDefaultConfig() { 265 ApfFilter.ApfConfiguration config = new ApfConfiguration(); 266 config.apfVersionSupported = 2; 267 config.apfRamSize = 4096; 268 config.multicastFilter = ALLOW_MULTICAST; 269 config.ieee802_3Filter = ALLOW_802_3_FRAMES; 270 config.ethTypeBlackList = new int[0]; 271 config.minRdnssLifetimeSec = MIN_RDNSS_LIFETIME_SEC; 272 config.minRdnssLifetimeSec = 67; 273 config.minMetricsSessionDurationMs = MIN_METRICS_SESSION_DURATIONS_MS; 274 return config; 275 } 276 assertPass(ApfV4Generator gen)277 private void assertPass(ApfV4Generator gen) throws ApfV4Generator.IllegalInstructionException { 278 mApfTestHelpers.assertPass(mApfVersion, gen); 279 } 280 assertDrop(ApfV4Generator gen)281 private void assertDrop(ApfV4Generator gen) throws ApfV4Generator.IllegalInstructionException { 282 mApfTestHelpers.assertDrop(mApfVersion, gen); 283 } 284 assertPass(byte[] program, byte[] packet)285 private void assertPass(byte[] program, byte[] packet) { 286 mApfTestHelpers.assertPass(mApfVersion, program, packet); 287 } 288 assertDrop(byte[] program, byte[] packet)289 private void assertDrop(byte[] program, byte[] packet) { 290 mApfTestHelpers.assertDrop(mApfVersion, program, packet); 291 } 292 assertPass(byte[] program, byte[] packet, int filterAge)293 private void assertPass(byte[] program, byte[] packet, int filterAge) { 294 mApfTestHelpers.assertPass(mApfVersion, program, packet, filterAge); 295 } 296 assertDrop(byte[] program, byte[] packet, int filterAge)297 private void assertDrop(byte[] program, byte[] packet, int filterAge) { 298 mApfTestHelpers.assertDrop(mApfVersion, program, packet, filterAge); 299 } 300 assertPass(ApfV4Generator gen, byte[] packet, int filterAge)301 private void assertPass(ApfV4Generator gen, byte[] packet, int filterAge) 302 throws ApfV4Generator.IllegalInstructionException { 303 mApfTestHelpers.assertPass(mApfVersion, gen, packet, filterAge); 304 } 305 assertDrop(ApfV4Generator gen, byte[] packet, int filterAge)306 private void assertDrop(ApfV4Generator gen, byte[] packet, int filterAge) 307 throws ApfV4Generator.IllegalInstructionException { 308 mApfTestHelpers.assertDrop(mApfVersion, gen, packet, filterAge); 309 } 310 assertDataMemoryContents(int expected, byte[] program, byte[] packet, byte[] data, byte[] expectedData)311 private void assertDataMemoryContents(int expected, byte[] program, byte[] packet, 312 byte[] data, byte[] expectedData) throws Exception { 313 mApfTestHelpers.assertDataMemoryContents(mApfVersion, expected, program, packet, data, 314 expectedData, false /* ignoreInterpreterVersion */); 315 } 316 assertDataMemoryContentsIgnoreVersion(int expected, byte[] program, byte[] packet, byte[] data, byte[] expectedData)317 private void assertDataMemoryContentsIgnoreVersion(int expected, byte[] program, 318 byte[] packet, byte[] data, byte[] expectedData) throws Exception { 319 mApfTestHelpers.assertDataMemoryContents(mApfVersion, expected, program, packet, data, 320 expectedData, true /* ignoreInterpreterVersion */); 321 } 322 assertVerdict(String msg, int expected, byte[] program, byte[] packet, int filterAge)323 private void assertVerdict(String msg, int expected, byte[] program, 324 byte[] packet, int filterAge) { 325 mApfTestHelpers.assertVerdict(mApfVersion, msg, expected, program, packet, filterAge); 326 } 327 assertVerdict(int expected, byte[] program, byte[] packet)328 private void assertVerdict(int expected, byte[] program, byte[] packet) { 329 mApfTestHelpers.assertVerdict(mApfVersion, expected, program, packet); 330 } 331 332 /** 333 * Test each instruction by generating a program containing the instruction, 334 * generating bytecode for that program and running it through the 335 * interpreter to verify it functions correctly. 336 */ 337 @Test testApfInstructions()338 public void testApfInstructions() throws IllegalInstructionException { 339 // Empty program should pass because having the program counter reach the 340 // location immediately after the program indicates the packet should be 341 // passed to the AP. 342 ApfV4Generator gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 343 assertPass(gen); 344 345 // Test pass opcode 346 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 347 gen.addPass(); 348 gen.addJump(DROP_LABEL); 349 assertPass(gen); 350 351 // Test jumping to pass label. 352 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 353 gen.addJump(PASS_LABEL); 354 byte[] program = gen.generate(); 355 assertEquals(1, program.length); 356 assertEquals((14 << 3) | (0 << 1) | 0, program[0]); 357 assertPass(program, new byte[MIN_PKT_SIZE], 0); 358 359 // Test jumping to drop label. 360 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 361 gen.addJump(DROP_LABEL); 362 program = gen.generate(); 363 assertEquals(2, program.length); 364 assertEquals((14 << 3) | (1 << 1) | 0, program[0]); 365 assertEquals(1, program[1]); 366 assertDrop(program, new byte[15], 15); 367 368 // Test jumping if equal to 0. 369 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 370 gen.addJumpIfR0Equals(0, DROP_LABEL); 371 assertDrop(gen); 372 373 // Test jumping if not equal to 0. 374 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 375 gen.addJumpIfR0NotEquals(0, DROP_LABEL); 376 assertPass(gen); 377 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 378 gen.addLoadImmediate(R0, 1); 379 gen.addJumpIfR0NotEquals(0, DROP_LABEL); 380 assertDrop(gen); 381 382 // Test jumping if registers equal. 383 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 384 gen.addJumpIfR0EqualsR1(DROP_LABEL); 385 assertDrop(gen); 386 387 // Test jumping if registers not equal. 388 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 389 gen.addJumpIfR0NotEqualsR1(DROP_LABEL); 390 assertPass(gen); 391 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 392 gen.addLoadImmediate(R0, 1); 393 gen.addJumpIfR0NotEqualsR1(DROP_LABEL); 394 assertDrop(gen); 395 396 // Test load immediate. 397 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 398 gen.addLoadImmediate(R0, 1234567890); 399 gen.addJumpIfR0Equals(1234567890, DROP_LABEL); 400 assertDrop(gen); 401 402 // Test add. 403 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 404 gen.addAdd(1234567890); 405 gen.addJumpIfR0Equals(1234567890, DROP_LABEL); 406 assertDrop(gen); 407 408 // Test add with a small signed negative value. 409 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 410 gen.addAdd(-1); 411 gen.addJumpIfR0Equals(-1, DROP_LABEL); 412 assertDrop(gen); 413 414 // Test subtract. 415 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 416 gen.addAdd(-1234567890); 417 gen.addJumpIfR0Equals(-1234567890, DROP_LABEL); 418 assertDrop(gen); 419 420 // Test or. 421 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 422 gen.addOr(1234567890); 423 gen.addJumpIfR0Equals(1234567890, DROP_LABEL); 424 assertDrop(gen); 425 426 // Test and. 427 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 428 gen.addLoadImmediate(R0, 1234567890); 429 gen.addAnd(123456789); 430 gen.addJumpIfR0Equals(1234567890 & 123456789, DROP_LABEL); 431 assertDrop(gen); 432 433 // Test left shift. 434 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 435 gen.addLoadImmediate(R0, 1234567890); 436 gen.addLeftShift(1); 437 gen.addJumpIfR0Equals(1234567890 << 1, DROP_LABEL); 438 assertDrop(gen); 439 440 // Test right shift. 441 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 442 gen.addLoadImmediate(R0, 1234567890); 443 gen.addRightShift(1); 444 gen.addJumpIfR0Equals(1234567890 >> 1, DROP_LABEL); 445 assertDrop(gen); 446 447 // Test multiply. 448 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 449 gen.addLoadImmediate(R0, 123456789); 450 gen.addMul(2); 451 gen.addJumpIfR0Equals(123456789 * 2, DROP_LABEL); 452 assertDrop(gen); 453 454 // Test divide. 455 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 456 gen.addLoadImmediate(R0, 1234567890); 457 gen.addDiv(2); 458 gen.addJumpIfR0Equals(1234567890 / 2, DROP_LABEL); 459 assertDrop(gen); 460 461 // Test divide by zero. 462 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 463 gen.addDiv(0); 464 gen.addJump(DROP_LABEL); 465 assertPass(gen); 466 467 // Test add. 468 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 469 gen.addLoadImmediate(R1, 1234567890); 470 gen.addAddR1ToR0(); 471 gen.addJumpIfR0Equals(1234567890, DROP_LABEL); 472 assertDrop(gen); 473 474 // Test subtract. 475 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 476 gen.addLoadImmediate(R1, -1234567890); 477 gen.addAddR1ToR0(); 478 gen.addJumpIfR0Equals(-1234567890, DROP_LABEL); 479 assertDrop(gen); 480 481 // Test or. 482 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 483 gen.addLoadImmediate(R1, 1234567890); 484 gen.addOrR0WithR1(); 485 gen.addJumpIfR0Equals(1234567890, DROP_LABEL); 486 assertDrop(gen); 487 488 // Test and. 489 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 490 gen.addLoadImmediate(R0, 1234567890); 491 gen.addLoadImmediate(R1, 123456789); 492 gen.addAndR0WithR1(); 493 gen.addJumpIfR0Equals(1234567890 & 123456789, DROP_LABEL); 494 assertDrop(gen); 495 496 // Test left shift. 497 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 498 gen.addLoadImmediate(R0, 1234567890); 499 gen.addLoadImmediate(R1, 1); 500 gen.addLeftShiftR0ByR1(); 501 gen.addJumpIfR0Equals(1234567890 << 1, DROP_LABEL); 502 assertDrop(gen); 503 504 // Test right shift. 505 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 506 gen.addLoadImmediate(R0, 1234567890); 507 gen.addLoadImmediate(R1, -1); 508 gen.addLeftShiftR0ByR1(); 509 gen.addJumpIfR0Equals(1234567890 >> 1, DROP_LABEL); 510 assertDrop(gen); 511 512 // Test multiply. 513 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 514 gen.addLoadImmediate(R0, 123456789); 515 gen.addLoadImmediate(R1, 2); 516 gen.addMulR0ByR1(); 517 gen.addJumpIfR0Equals(123456789 * 2, DROP_LABEL); 518 assertDrop(gen); 519 520 // Test divide. 521 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 522 gen.addLoadImmediate(R0, 1234567890); 523 gen.addLoadImmediate(R1, 2); 524 gen.addDivR0ByR1(); 525 gen.addJumpIfR0Equals(1234567890 / 2, DROP_LABEL); 526 assertDrop(gen); 527 528 // Test divide by zero. 529 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 530 gen.addDivR0ByR1(); 531 gen.addJump(DROP_LABEL); 532 assertPass(gen); 533 534 // Test byte load. 535 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 536 gen.addLoad8intoR0(1); 537 gen.addJumpIfR0Equals(45, DROP_LABEL); 538 assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0); 539 540 // Test out of bounds load. 541 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 542 gen.addLoad8intoR0(16); 543 gen.addJumpIfR0Equals(0, DROP_LABEL); 544 assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0); 545 546 // Test half-word load. 547 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 548 gen.addLoad16intoR0(1); 549 gen.addJumpIfR0Equals((45 << 8) | 67, DROP_LABEL); 550 assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0); 551 552 // Test word load. 553 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 554 gen.addLoad32intoR0(1); 555 gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, DROP_LABEL); 556 assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0); 557 558 // Test byte indexed load. 559 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 560 gen.addLoadImmediate(R1, 1); 561 gen.addLoad8R1IndexedIntoR0(0); 562 gen.addJumpIfR0Equals(45, DROP_LABEL); 563 assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0); 564 565 // Test out of bounds indexed load. 566 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 567 gen.addLoadImmediate(R1, 8); 568 gen.addLoad8R1IndexedIntoR0(8); 569 gen.addJumpIfR0Equals(0, DROP_LABEL); 570 assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0); 571 572 // Test half-word indexed load. 573 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 574 gen.addLoadImmediate(R1, 1); 575 gen.addLoad16R1IndexedIntoR0(0); 576 gen.addJumpIfR0Equals((45 << 8) | 67, DROP_LABEL); 577 assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0); 578 579 // Test word indexed load. 580 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 581 gen.addLoadImmediate(R1, 1); 582 gen.addLoad32R1IndexedIntoR0(0); 583 gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, DROP_LABEL); 584 assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0); 585 586 // Test jumping if greater than. 587 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 588 gen.addJumpIfR0GreaterThan(0, DROP_LABEL); 589 assertPass(gen); 590 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 591 gen.addLoadImmediate(R0, 1); 592 gen.addJumpIfR0GreaterThan(0, DROP_LABEL); 593 assertDrop(gen); 594 595 // Test jumping if less than. 596 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 597 gen.addJumpIfR0LessThan(0, DROP_LABEL); 598 assertPass(gen); 599 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 600 gen.addJumpIfR0LessThan(1, DROP_LABEL); 601 assertDrop(gen); 602 603 // Test jumping if any bits set. 604 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 605 gen.addJumpIfR0AnyBitsSet(3, DROP_LABEL); 606 assertPass(gen); 607 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 608 gen.addLoadImmediate(R0, 1); 609 gen.addJumpIfR0AnyBitsSet(3, DROP_LABEL); 610 assertDrop(gen); 611 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 612 gen.addLoadImmediate(R0, 3); 613 gen.addJumpIfR0AnyBitsSet(3, DROP_LABEL); 614 assertDrop(gen); 615 616 // Test jumping if register greater than. 617 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 618 gen.addJumpIfR0GreaterThanR1(DROP_LABEL); 619 assertPass(gen); 620 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 621 gen.addLoadImmediate(R0, 2); 622 gen.addLoadImmediate(R1, 1); 623 gen.addJumpIfR0GreaterThanR1(DROP_LABEL); 624 assertDrop(gen); 625 626 // Test jumping if register less than. 627 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 628 gen.addJumpIfR0LessThanR1(DROP_LABEL); 629 assertPass(gen); 630 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 631 gen.addLoadImmediate(R1, 1); 632 gen.addJumpIfR0LessThanR1(DROP_LABEL); 633 assertDrop(gen); 634 635 // Test jumping if any bits set in register. 636 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 637 gen.addLoadImmediate(R1, 3); 638 gen.addJumpIfR0AnyBitsSetR1(DROP_LABEL); 639 assertPass(gen); 640 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 641 gen.addLoadImmediate(R1, 3); 642 gen.addLoadImmediate(R0, 1); 643 gen.addJumpIfR0AnyBitsSetR1(DROP_LABEL); 644 assertDrop(gen); 645 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 646 gen.addLoadImmediate(R1, 3); 647 gen.addLoadImmediate(R0, 3); 648 gen.addJumpIfR0AnyBitsSetR1(DROP_LABEL); 649 assertDrop(gen); 650 651 // Test load from memory. 652 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 653 gen.addLoadFromMemory(R0, MemorySlot.SLOT_0); 654 gen.addJumpIfR0Equals(0, DROP_LABEL); 655 assertDrop(gen); 656 657 // Test store to memory. 658 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 659 gen.addLoadImmediate(R1, 1234567890); 660 gen.addStoreToMemory(MemorySlot.RAM_LEN, R1); 661 gen.addLoadFromMemory(R0, MemorySlot.RAM_LEN); 662 gen.addJumpIfR0Equals(1234567890, DROP_LABEL); 663 assertDrop(gen); 664 665 // Test filter age pre-filled memory. 666 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 667 gen.addLoadFromMemory(R0, MemorySlot.FILTER_AGE_SECONDS); 668 gen.addJumpIfR0Equals(123, DROP_LABEL); 669 assertDrop(gen, new byte[MIN_PKT_SIZE], 123); 670 671 // Test packet size pre-filled memory. 672 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 673 gen.addLoadFromMemory(R0, MemorySlot.PACKET_SIZE); 674 gen.addJumpIfR0Equals(MIN_PKT_SIZE, DROP_LABEL); 675 assertDrop(gen); 676 677 // Test IPv4 header size pre-filled memory. 678 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 679 gen.addLoadFromMemory(R0, MemorySlot.IPV4_HEADER_SIZE); 680 gen.addJumpIfR0Equals(20, DROP_LABEL); 681 assertDrop(gen, new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,8,0,0x45,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0); 682 683 // Test not. 684 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 685 gen.addLoadImmediate(R0, 1234567890); 686 gen.addNot(R0); 687 gen.addJumpIfR0Equals(~1234567890, DROP_LABEL); 688 assertDrop(gen); 689 690 // Test negate. 691 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 692 gen.addLoadImmediate(R0, 1234567890); 693 gen.addNeg(R0); 694 gen.addJumpIfR0Equals(-1234567890, DROP_LABEL); 695 assertDrop(gen); 696 697 // Test move. 698 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 699 gen.addLoadImmediate(R1, 1234567890); 700 gen.addMove(R0); 701 gen.addJumpIfR0Equals(1234567890, DROP_LABEL); 702 assertDrop(gen); 703 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 704 gen.addLoadImmediate(R0, 1234567890); 705 gen.addMove(R1); 706 gen.addJumpIfR0Equals(1234567890, DROP_LABEL); 707 assertDrop(gen); 708 709 // Test swap. 710 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 711 gen.addLoadImmediate(R1, 1234567890); 712 gen.addSwap(); 713 gen.addJumpIfR0Equals(1234567890, DROP_LABEL); 714 assertDrop(gen); 715 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 716 gen.addLoadImmediate(R0, 1234567890); 717 gen.addSwap(); 718 gen.addJumpIfR0Equals(0, DROP_LABEL); 719 assertDrop(gen); 720 721 // Test jump if bytes not equal. 722 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 723 gen.addLoadImmediate(R0, 1); 724 gen.addJumpIfBytesAtR0NotEqual(new byte[]{123}, DROP_LABEL); 725 program = gen.generate(); 726 assertEquals(6, program.length); 727 assertEquals((13 << 3) | (1 << 1) | 0, program[0]); 728 assertEquals(1, program[1]); 729 assertEquals(((20 << 3) | (1 << 1) | 0) - 256, program[2]); 730 assertEquals(1, program[3]); 731 assertEquals(1, program[4]); 732 assertEquals(123, program[5]); 733 assertDrop(program, new byte[MIN_PKT_SIZE], 0); 734 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 735 gen.addLoadImmediate(R0, 1); 736 gen.addJumpIfBytesAtR0NotEqual(new byte[]{123}, DROP_LABEL); 737 byte[] packet123 = {0,123,0,0,0,0,0,0,0,0,0,0,0,0,0}; 738 assertPass(gen, packet123, 0); 739 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 740 gen.addJumpIfBytesAtR0NotEqual(new byte[]{123}, DROP_LABEL); 741 assertDrop(gen, packet123, 0); 742 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 743 gen.addLoadImmediate(R0, 1); 744 gen.addJumpIfBytesAtR0NotEqual(new byte[]{1, 2, 30, 4, 5}, DROP_LABEL); 745 byte[] packet12345 = {0,1,2,3,4,5,0,0,0,0,0,0,0,0,0}; 746 assertDrop(gen, packet12345, 0); 747 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 748 gen.addLoadImmediate(R0, 1); 749 gen.addJumpIfBytesAtR0NotEqual(new byte[]{1, 2, 3, 4, 5}, DROP_LABEL); 750 assertPass(gen, packet12345, 0); 751 } 752 753 @Test(expected = ApfV4Generator.IllegalInstructionException.class) testApfGeneratorWantsV2OrGreater()754 public void testApfGeneratorWantsV2OrGreater() throws Exception { 755 // The minimum supported APF version is 2. 756 new ApfV4Generator(1, mRamSize, mClampSize); 757 } 758 759 @Test testApfDataOpcodesWantApfV3()760 public void testApfDataOpcodesWantApfV3() throws IllegalInstructionException, Exception { 761 ApfV4Generator gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 762 try { 763 gen.addStoreData(R0, 0); 764 fail(); 765 } catch (IllegalInstructionException expected) { 766 /* pass */ 767 } 768 try { 769 gen.addLoadData(R0, 0); 770 fail(); 771 } catch (IllegalInstructionException expected) { 772 /* pass */ 773 } 774 } 775 776 /** 777 * Test that the generator emits immediates using the shortest possible encoding. 778 */ 779 @Test testImmediateEncoding()780 public void testImmediateEncoding() throws IllegalInstructionException { 781 ApfV4Generator gen; 782 783 // 0-byte immediate: li R0, 0 784 gen = new ApfV4Generator(APF_VERSION_4, mRamSize, mClampSize); 785 gen.addLoadImmediate(R0, 0); 786 assertProgramEquals(new byte[]{LI_OP | SIZE0}, gen.generate()); 787 788 // 1-byte immediate: li R0, 42 789 gen = new ApfV4Generator(APF_VERSION_4, mRamSize, mClampSize); 790 gen.addLoadImmediate(R0, 42); 791 assertProgramEquals(new byte[]{LI_OP | SIZE8, 42}, gen.generate()); 792 793 // 2-byte immediate: li R1, 0x1234 794 gen = new ApfV4Generator(APF_VERSION_4, mRamSize, mClampSize); 795 gen.addLoadImmediate(R1, 0x1234); 796 assertProgramEquals(new byte[]{LI_OP | SIZE16 | R1_REG, 0x12, 0x34}, gen.generate()); 797 798 // 4-byte immediate: li R0, 0x12345678 799 gen = new ApfV4Generator(APF_VERSION_3, mRamSize, mClampSize); 800 gen.addLoadImmediate(R0, 0x12345678); 801 assertProgramEquals( 802 new byte[]{LI_OP | SIZE32, 0x12, 0x34, 0x56, 0x78}, 803 gen.generate()); 804 } 805 806 /** 807 * Test that the generator emits negative immediates using the shortest possible encoding. 808 */ 809 @Test testNegativeImmediateEncoding()810 public void testNegativeImmediateEncoding() throws IllegalInstructionException { 811 ApfV4Generator gen; 812 813 // 1-byte negative immediate: li R0, -42 814 gen = new ApfV4Generator(APF_VERSION_3, mRamSize, mClampSize); 815 gen.addLoadImmediate(R0, -42); 816 assertProgramEquals(new byte[]{LI_OP | SIZE8, -42}, gen.generate()); 817 818 // 2-byte negative immediate: li R1, -0x1122 819 gen = new ApfV4Generator(APF_VERSION_3, mRamSize, mClampSize); 820 gen.addLoadImmediate(R1, -0x1122); 821 assertProgramEquals(new byte[]{LI_OP | SIZE16 | R1_REG, (byte)0xEE, (byte)0xDE}, 822 gen.generate()); 823 824 // 4-byte negative immediate: li R0, -0x11223344 825 gen = new ApfV4Generator(APF_VERSION_3, mRamSize, mClampSize); 826 gen.addLoadImmediate(R0, -0x11223344); 827 assertProgramEquals( 828 new byte[]{LI_OP | SIZE32, (byte)0xEE, (byte)0xDD, (byte)0xCC, (byte)0xBC}, 829 gen.generate()); 830 } 831 832 /** 833 * Test that the generator correctly emits positive and negative immediates for LDDW/STDW. 834 */ 835 @Test testLoadStoreDataEncoding()836 public void testLoadStoreDataEncoding() throws IllegalInstructionException { 837 ApfV4Generator gen; 838 839 // Load data with no offset: lddw R0, [0 + r1] 840 gen = new ApfV4Generator(APF_VERSION_3, mRamSize, mClampSize); 841 gen.addLoadData(R0, 0); 842 assertProgramEquals(new byte[]{LDDW_OP | SIZE0}, gen.generate()); 843 844 // Store data with 8bit negative offset: lddw r0, [-42 + r1] 845 gen = new ApfV4Generator(APF_VERSION_3, mRamSize, mClampSize); 846 gen.addStoreData(R0, -42); 847 assertProgramEquals(new byte[]{STDW_OP | SIZE8, -42}, gen.generate()); 848 849 // Store data to R1 with 16bit negative offset: stdw r1, [-0x1122 + r0] 850 gen = new ApfV4Generator(APF_VERSION_3, mRamSize, mClampSize); 851 gen.addStoreData(R1, -0x1122); 852 assertProgramEquals(new byte[]{STDW_OP | SIZE16 | R1_REG, (byte)0xEE, (byte)0xDE}, 853 gen.generate()); 854 855 // Load data to R1 with 32bit negative offset: lddw r1, [0xDEADBEEF + r0] 856 gen = new ApfV4Generator(APF_VERSION_3, mRamSize, mClampSize); 857 gen.addLoadData(R1, 0xDEADBEEF); 858 assertProgramEquals( 859 new byte[]{LDDW_OP | SIZE32 | R1_REG, 860 (byte)0xDE, (byte)0xAD, (byte)0xBE, (byte)0xEF}, 861 gen.generate()); 862 } 863 864 /** 865 * Test that the interpreter correctly executes STDW with a negative 8bit offset 866 */ 867 @Test testApfDataWrite()868 public void testApfDataWrite() throws IllegalInstructionException, Exception { 869 byte[] packet = new byte[MIN_PKT_SIZE]; 870 byte[] data = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; 871 byte[] expected_data = data.clone(); 872 873 // No memory access instructions: should leave the data segment untouched. 874 ApfV4Generator gen = new ApfV4Generator(APF_VERSION_3, mRamSize, mClampSize); 875 assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data); 876 877 // Expect value 0x87654321 to be stored starting from address -11 from the end of the 878 // data buffer, in big-endian order. 879 gen = new ApfV4Generator(APF_VERSION_3, mRamSize, mClampSize); 880 gen.addLoadImmediate(R0, 0x87654321); 881 gen.addLoadImmediate(R1, -5); 882 gen.addStoreData(R0, -6); // -5 + -6 = -11 (offset +5 with data_len=16) 883 expected_data[5] = (byte)0x87; 884 expected_data[6] = (byte)0x65; 885 expected_data[7] = (byte)0x43; 886 expected_data[8] = (byte)0x21; 887 assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data); 888 } 889 890 /** 891 * Test that the interpreter correctly executes LDDW with a negative 16bit offset 892 */ 893 @Test testApfDataRead()894 public void testApfDataRead() throws IllegalInstructionException, Exception { 895 // Program that DROPs if address 10 (-6) contains 0x87654321. 896 ApfV4Generator gen = new ApfV4Generator(APF_VERSION_3, mRamSize, mClampSize); 897 gen.addLoadImmediate(R1, 1000); 898 gen.addLoadData(R0, -1006); // 1000 + -1006 = -6 (offset +10 with data_len=16) 899 gen.addJumpIfR0Equals(0x87654321, DROP_LABEL); 900 byte[] program = gen.generate(); 901 byte[] packet = new byte[MIN_PKT_SIZE]; 902 903 // Content is incorrect (last byte does not match) -> PASS 904 byte[] data = new byte[16]; 905 data[10] = (byte)0x87; 906 data[11] = (byte)0x65; 907 data[12] = (byte)0x43; 908 data[13] = (byte)0x00; // != 0x21 909 byte[] expected_data = data.clone(); 910 assertDataMemoryContents(PASS, program, packet, data, expected_data); 911 912 // Fix the last byte -> conditional jump taken -> DROP 913 data[13] = (byte)0x21; 914 expected_data = data; 915 assertDataMemoryContents(DROP, program, packet, data, expected_data); 916 } 917 918 /** 919 * Test that the interpreter correctly executes LDDW followed by a STDW. 920 * To cover a few more edge cases, LDDW has a 0bit offset, while STDW has a positive 8bit 921 * offset. 922 */ 923 @Test testApfDataReadModifyWrite()924 public void testApfDataReadModifyWrite() throws IllegalInstructionException, Exception { 925 ApfV4Generator gen = new ApfV4Generator(APF_VERSION_3, mRamSize, mClampSize); 926 gen.addLoadImmediate(R1, -22); 927 gen.addLoadData(R0, 0); // Load from address 32 -22 + 0 = 10 928 gen.addAdd(0x78453412); // 87654321 + 78453412 = FFAA7733 929 gen.addStoreData(R0, 4); // Write back to address 32 -22 + 4 = 14 930 931 byte[] packet = new byte[MIN_PKT_SIZE]; 932 byte[] data = new byte[32]; 933 data[10] = (byte)0x87; 934 data[11] = (byte)0x65; 935 data[12] = (byte)0x43; 936 data[13] = (byte)0x21; 937 byte[] expected_data = data.clone(); 938 expected_data[14] = (byte)0xFF; 939 expected_data[15] = (byte)0xAA; 940 expected_data[16] = (byte)0x77; 941 expected_data[17] = (byte)0x33; 942 assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data); 943 } 944 945 @Test testApfDataBoundChecking()946 public void testApfDataBoundChecking() throws IllegalInstructionException, Exception { 947 byte[] packet = new byte[MIN_PKT_SIZE]; 948 byte[] data = new byte[32]; 949 byte[] expected_data = data; 950 951 // Program that DROPs unconditionally. This is our the baseline. 952 ApfV4Generator gen = new ApfV4Generator(APF_VERSION_3, mRamSize, mClampSize); 953 gen.addLoadImmediate(R0, 3); 954 gen.addLoadData(R1, 7); 955 gen.addJump(DROP_LABEL); 956 assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data); 957 958 // Same program as before, but this time we're trying to load past the end of the data. 959 // 3 instructions, all normal opcodes (LI, LDDW, JMP) with 1 byte immediate = 6 byte program 960 // 32 byte data length, for a total of 38 byte ram len. 961 // APFv6 needs to round this up to be a multiple of 4, so 40. 962 gen = new ApfV4Generator(APF_VERSION_3, mRamSize, mClampSize); 963 gen.addLoadImmediate(R0, 20); 964 if (mApfVersion == 4) { 965 gen.addLoadData(R1, 15); // R0(20)+15+U32[0..3] >= 6 prog + 32 data, so invalid 966 } else { 967 gen.addLoadData(R1, 17); // R0(20)+17+U32[0..3] >= 6 prog + 2 pad + 32 data, so invalid 968 } 969 gen.addJump(DROP_LABEL); // Not reached. 970 assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data); 971 972 // Subtracting an immediate should work... 973 gen = new ApfV4Generator(APF_VERSION_3, mRamSize, mClampSize); 974 gen.addLoadImmediate(R0, 20); 975 gen.addLoadData(R1, -4); 976 gen.addJump(DROP_LABEL); 977 assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data); 978 979 // ...and underflowing simply wraps around to the end of the buffer... 980 gen = new ApfV4Generator(APF_VERSION_3, mRamSize, mClampSize); 981 gen.addLoadImmediate(R0, 20); 982 gen.addLoadData(R1, -30); 983 gen.addJump(DROP_LABEL); 984 assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data); 985 986 // ...but doesn't allow accesses before the start of the buffer 987 gen = new ApfV4Generator(APF_VERSION_3, mRamSize, mClampSize); 988 gen.addLoadImmediate(R0, 20); 989 gen.addLoadData(R1, -1000); 990 gen.addJump(DROP_LABEL); // Not reached. 991 assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data); 992 } 993 pretendPacketReceived(byte[] packet)994 private void pretendPacketReceived(byte[] packet) 995 throws InterruptedIOException, ErrnoException { 996 Os.write(mWriteSocket, packet, 0, packet.length); 997 } 998 getApfFilter(ApfFilter.ApfConfiguration config)999 private ApfFilter getApfFilter(ApfFilter.ApfConfiguration config) { 1000 AtomicReference<ApfFilter> apfFilter = new AtomicReference<>(); 1001 mHandler.post(() -> 1002 apfFilter.set(new ApfFilter(mHandler, mContext, config, TEST_PARAMS, 1003 mApfController, mNetworkQuirkMetrics, mDependencies))); 1004 HandlerUtils.waitForIdle(mHandler, TIMEOUT_MS); 1005 return apfFilter.get(); 1006 } 1007 1008 /** 1009 * Generate APF program, run pcap file though APF filter, then check all the packets in the file 1010 * should be dropped. 1011 */ 1012 @Test testApfFilterPcapFile()1013 public void testApfFilterPcapFile() throws Exception { 1014 final byte[] MOCK_PCAP_IPV4_ADDR = {(byte) 172, 16, 7, (byte) 151}; 1015 String pcapFilename = stageFile(R.raw.apfPcap); 1016 LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_PCAP_IPV4_ADDR), 16); 1017 LinkProperties lp = new LinkProperties(); 1018 lp.addLinkAddress(link); 1019 1020 ApfConfiguration config = getDefaultConfig(); 1021 config.apfVersionSupported = 4; 1022 config.apfRamSize = 1700; 1023 config.multicastFilter = DROP_MULTICAST; 1024 config.ieee802_3Filter = DROP_802_3_FRAMES; 1025 final ApfFilter apfFilter = getApfFilter(config); 1026 mApfTestHelpers.consumeInstalledProgram(mApfController, 2 /* installCnt */); 1027 apfFilter.setLinkProperties(lp); 1028 byte[] program = 1029 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 1030 byte[] data = new byte[Counter.totalSize()]; 1031 final boolean result; 1032 1033 result = mApfTestHelpers.dropsAllPackets( 1034 mApfVersion, program, data, pcapFilename); 1035 Log.i(TAG, "testApfFilterPcapFile(): Data counters: " + HexDump.toHexString(data, false)); 1036 1037 assertTrue("Failed to drop all packets by filter. \nAPF counters:" + 1038 HexDump.toHexString(data, false), result); 1039 } 1040 1041 private static final int ETH_HEADER_LEN = 14; 1042 private static final int ETH_DEST_ADDR_OFFSET = 0; 1043 private static final int ETH_ETHERTYPE_OFFSET = 12; 1044 private static final byte[] ETH_BROADCAST_MAC_ADDRESS = 1045 {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff }; 1046 private static final byte[] ETH_MULTICAST_MDNS_v4_MAC_ADDRESS = 1047 {(byte) 0x01, (byte) 0x00, (byte) 0x5e, (byte) 0x00, (byte) 0x00, (byte) 0xfb}; 1048 private static final byte[] ETH_MULTICAST_MDNS_V6_MAC_ADDRESS = 1049 {(byte) 0x33, (byte) 0x33, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xfb}; 1050 1051 private static final int IP_HEADER_OFFSET = ETH_HEADER_LEN; 1052 1053 private static final int IPV4_HEADER_LEN = 20; 1054 private static final int IPV4_PROTOCOL_OFFSET = IP_HEADER_OFFSET + 9; 1055 private static final int IPV4_DEST_ADDR_OFFSET = IP_HEADER_OFFSET + 16; 1056 1057 private static final int IPV4_TCP_HEADER_OFFSET = IP_HEADER_OFFSET + IPV4_HEADER_LEN; 1058 1059 private static final int IPV4_UDP_HEADER_OFFSET = IP_HEADER_OFFSET + IPV4_HEADER_LEN; 1060 private static final byte[] IPV4_BROADCAST_ADDRESS = 1061 {(byte) 255, (byte) 255, (byte) 255, (byte) 255}; 1062 1063 private static final int IPV6_HEADER_LEN = 40; 1064 private static final int IPV6_PAYLOAD_LENGTH_OFFSET = IP_HEADER_OFFSET + 4; 1065 private static final int IPV6_NEXT_HEADER_OFFSET = IP_HEADER_OFFSET + 6; 1066 private static final int IPV6_SRC_ADDR_OFFSET = IP_HEADER_OFFSET + 8; 1067 private static final int IPV6_DEST_ADDR_OFFSET = IP_HEADER_OFFSET + 24; 1068 private static final int IPV6_PAYLOAD_OFFSET = IP_HEADER_OFFSET + IPV6_HEADER_LEN; 1069 // The IPv6 all nodes address ff02::1 1070 private static final byte[] IPV6_ALL_NODES_ADDRESS = 1071 { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; 1072 private static final byte[] IPV6_ALL_ROUTERS_ADDRESS = 1073 { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 }; 1074 private static final byte[] IPV6_SOLICITED_NODE_MULTICAST_ADDRESS = { 1075 (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1076 (byte) 0xff, (byte) 0xab, (byte) 0xcd, (byte) 0xef, 1077 }; 1078 1079 private static final int ICMP6_TYPE_OFFSET = IP_HEADER_OFFSET + IPV6_HEADER_LEN; 1080 private static final int ICMP6_ROUTER_SOLICITATION = 133; 1081 private static final int ICMP6_ROUTER_ADVERTISEMENT = 134; 1082 private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136; 1083 1084 private static final int ICMP6_RA_HEADER_LEN = 16; 1085 private static final int ICMP6_RA_CHECKSUM_OFFSET = 1086 IP_HEADER_OFFSET + IPV6_HEADER_LEN + 2; 1087 private static final int ICMP6_RA_REACHABLE_TIME_OFFSET = 1088 IP_HEADER_OFFSET + IPV6_HEADER_LEN + 8; 1089 private static final int ICMP6_RA_OPTION_OFFSET = 1090 IP_HEADER_OFFSET + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN; 1091 1092 private static final int ICMP6_PREFIX_OPTION_TYPE = 3; 1093 private static final int ICMP6_PREFIX_OPTION_LEN = 32; 1094 1095 // From RFC6106: Recursive DNS Server option 1096 private static final int ICMP6_RDNSS_OPTION_TYPE = 25; 1097 // From RFC6106: DNS Search List option 1098 private static final int ICMP6_DNSSL_OPTION_TYPE = 31; 1099 1100 // From RFC4191: Route Information option 1101 private static final int ICMP6_ROUTE_INFO_OPTION_TYPE = 24; 1102 // Above three options all have the same format: 1103 private static final int ICMP6_4_BYTE_OPTION_LEN = 8; 1104 1105 private static final int UDP_HEADER_LEN = 8; 1106 private static final int UDP_DESTINATION_PORT_OFFSET = ETH_HEADER_LEN + 22; 1107 1108 private static final int DHCP_CLIENT_PORT = 68; 1109 private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 48; 1110 1111 private static final int ARP_HEADER_OFFSET = ETH_HEADER_LEN; 1112 private static final byte[] ARP_IPV4_REQUEST_HEADER = { 1113 0, 1, // Hardware type: Ethernet (1) 1114 8, 0, // Protocol type: IP (0x0800) 1115 6, // Hardware size: 6 1116 4, // Protocol size: 4 1117 0, 1 // Opcode: request (1) 1118 }; 1119 private static final byte[] ARP_IPV4_REPLY_HEADER = { 1120 0, 1, // Hardware type: Ethernet (1) 1121 8, 0, // Protocol type: IP (0x0800) 1122 6, // Hardware size: 6 1123 4, // Protocol size: 4 1124 0, 2 // Opcode: reply (2) 1125 }; 1126 private static final int ARP_SOURCE_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 14; 1127 private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 24; 1128 1129 private static final byte[] MOCK_IPV4_ADDR = {10, 0, 0, 1}; 1130 private static final byte[] MOCK_BROADCAST_IPV4_ADDR = {10, 0, 31, (byte) 255}; // prefix = 19 1131 private static final byte[] MOCK_MULTICAST_IPV4_ADDR = {(byte) 224, 0, 0, 1}; 1132 private static final byte[] ANOTHER_IPV4_ADDR = {10, 0, 0, 2}; 1133 private static final byte[] IPV4_SOURCE_ADDR = {10, 0, 0, 3}; 1134 private static final byte[] ANOTHER_IPV4_SOURCE_ADDR = {(byte) 192, 0, 2, 1}; 1135 private static final byte[] BUG_PROBE_SOURCE_ADDR1 = {0, 0, 1, 2}; 1136 private static final byte[] BUG_PROBE_SOURCE_ADDR2 = {3, 4, 0, 0}; 1137 private static final byte[] IPV4_ANY_HOST_ADDR = {0, 0, 0, 0}; 1138 private static final byte[] IPV4_MDNS_MULTICAST_ADDR = {(byte) 224, 0, 0, (byte) 251}; 1139 private static final byte[] IPV6_MDNS_MULTICAST_ADDR = 1140 {(byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xfb}; 1141 private static final int MDNS_UDP_PORT = 5353; 1142 setIpv4VersionFields(ByteBuffer packet)1143 private static void setIpv4VersionFields(ByteBuffer packet) { 1144 packet.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IP); 1145 packet.put(IP_HEADER_OFFSET, (byte) 0x45); 1146 } 1147 setIpv6VersionFields(ByteBuffer packet)1148 private static void setIpv6VersionFields(ByteBuffer packet) { 1149 packet.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IPV6); 1150 packet.put(IP_HEADER_OFFSET, (byte) 0x60); 1151 } 1152 makeIpv4Packet(int proto)1153 private static ByteBuffer makeIpv4Packet(int proto) { 1154 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1155 setIpv4VersionFields(packet); 1156 packet.put(IPV4_PROTOCOL_OFFSET, (byte) proto); 1157 return packet; 1158 } 1159 makeIpv6Packet(int nextHeader)1160 private static ByteBuffer makeIpv6Packet(int nextHeader) { 1161 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1162 setIpv6VersionFields(packet); 1163 packet.put(IPV6_NEXT_HEADER_OFFSET, (byte) nextHeader); 1164 return packet; 1165 } 1166 1167 @Test testApfFilterIPv4()1168 public void testApfFilterIPv4() throws Exception { 1169 LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19); 1170 LinkProperties lp = new LinkProperties(); 1171 lp.addLinkAddress(link); 1172 1173 ApfConfiguration config = getDefaultConfig(); 1174 config.multicastFilter = DROP_MULTICAST; 1175 final ApfFilter apfFilter = getApfFilter(config); 1176 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 1177 apfFilter.setLinkProperties(lp); 1178 1179 byte[] program = 1180 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 1181 1182 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1183 if (SdkLevel.isAtLeastV()) { 1184 // Verify empty packet of 100 zero bytes is dropped 1185 assertDrop(program, packet.array()); 1186 } else { 1187 // Verify empty packet of 100 zero bytes is passed 1188 assertPass(program, packet.array()); 1189 } 1190 1191 // Verify unicast IPv4 packet is passed 1192 put(packet, ETH_DEST_ADDR_OFFSET, TEST_MAC_ADDR); 1193 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 1194 put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_IPV4_ADDR); 1195 assertPass(program, packet.array()); 1196 1197 // Verify L2 unicast to IPv4 broadcast addresses is dropped (b/30231088) 1198 put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS); 1199 assertDrop(program, packet.array()); 1200 put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR); 1201 assertDrop(program, packet.array()); 1202 1203 // Verify multicast/broadcast IPv4, not DHCP to us, is dropped 1204 put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS); 1205 assertDrop(program, packet.array()); 1206 packet.put(IP_HEADER_OFFSET, (byte) 0x45); 1207 assertDrop(program, packet.array()); 1208 packet.put(IPV4_PROTOCOL_OFFSET, (byte)IPPROTO_UDP); 1209 assertDrop(program, packet.array()); 1210 packet.putShort(UDP_DESTINATION_PORT_OFFSET, (short)DHCP_CLIENT_PORT); 1211 assertDrop(program, packet.array()); 1212 put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_MULTICAST_IPV4_ADDR); 1213 assertDrop(program, packet.array()); 1214 put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR); 1215 assertDrop(program, packet.array()); 1216 put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS); 1217 assertDrop(program, packet.array()); 1218 1219 // Verify broadcast IPv4 DHCP to us is passed 1220 put(packet, DHCP_CLIENT_MAC_OFFSET, TEST_MAC_ADDR); 1221 assertPass(program, packet.array()); 1222 1223 // Verify unicast IPv4 DHCP to us is passed 1224 put(packet, ETH_DEST_ADDR_OFFSET, TEST_MAC_ADDR); 1225 assertPass(program, packet.array()); 1226 } 1227 1228 @Test testApfFilterIPv6()1229 public void testApfFilterIPv6() throws Exception { 1230 ApfConfiguration config = getDefaultConfig(); 1231 ApfFilter apfFilter = getApfFilter(config); 1232 byte[] program = 1233 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 1234 1235 // Verify empty IPv6 packet is passed 1236 ByteBuffer packet = makeIpv6Packet(IPPROTO_UDP); 1237 assertPass(program, packet.array()); 1238 1239 // Verify empty ICMPv6 packet is passed 1240 packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6); 1241 assertPass(program, packet.array()); 1242 1243 // Verify empty ICMPv6 NA packet is passed 1244 packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_NEIGHBOR_ANNOUNCEMENT); 1245 assertPass(program, packet.array()); 1246 1247 // Verify ICMPv6 NA to ff02::1 is dropped 1248 put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_NODES_ADDRESS); 1249 assertDrop(program, packet.array()); 1250 1251 // Verify ICMPv6 NA to ff02::2 is dropped 1252 put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_ROUTERS_ADDRESS); 1253 assertDrop(program, packet.array()); 1254 1255 // Verify ICMPv6 NA to Solicited-Node Multicast is passed 1256 put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_SOLICITED_NODE_MULTICAST_ADDRESS); 1257 assertPass(program, packet.array()); 1258 1259 // Verify ICMPv6 RS to any is dropped 1260 packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_SOLICITATION); 1261 assertDrop(program, packet.array()); 1262 put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_ROUTERS_ADDRESS); 1263 assertDrop(program, packet.array()); 1264 } 1265 fillQuestionSection(ByteBuffer buf, String... qnames)1266 private static void fillQuestionSection(ByteBuffer buf, String... qnames) throws IOException { 1267 buf.put(new DnsPacket.DnsHeader(0 /* id */, 0 /* flags */, qnames.length, 0 /* ancount */) 1268 .getBytes()); 1269 for (String qname : qnames) { 1270 buf.put(DnsPacket.DnsRecord.makeQuestion(qname, 0 /* nsType */, 0 /* nsClass */) 1271 .getBytes()); 1272 } 1273 } 1274 makeMdnsV4Packet(String... qnames)1275 private static byte[] makeMdnsV4Packet(String... qnames) throws IOException { 1276 final ByteBuffer buf = ByteBuffer.wrap(new byte[256]); 1277 final PacketBuilder builder = new PacketBuilder(buf); 1278 builder.writeL2Header(MacAddress.fromString("11:22:33:44:55:66"), 1279 MacAddress.fromBytes(ETH_MULTICAST_MDNS_v4_MAC_ADDRESS), 1280 (short) ETH_P_IP); 1281 builder.writeIpv4Header((byte) 0 /* tos */, (short) 0 /* id */, 1282 (short) 0 /* flagsAndFragmentOffset */, (byte) 0 /* ttl */, (byte) IPPROTO_UDP, 1283 (Inet4Address) Inet4Address.getByAddress(IPV4_SOURCE_ADDR), 1284 (Inet4Address) Inet4Address.getByAddress(IPV4_MDNS_MULTICAST_ADDR)); 1285 builder.writeUdpHeader((short) MDNS_UDP_PORT, (short) MDNS_UDP_PORT); 1286 fillQuestionSection(buf, qnames); 1287 return builder.finalizePacket().array(); 1288 } 1289 makeMdnsV6Packet(String... qnames)1290 private static byte[] makeMdnsV6Packet(String... qnames) throws IOException { 1291 ByteBuffer buf = ByteBuffer.wrap(new byte[256]); 1292 final PacketBuilder builder = new PacketBuilder(buf); 1293 builder.writeL2Header(MacAddress.fromString("11:22:33:44:55:66"), 1294 MacAddress.fromBytes(ETH_MULTICAST_MDNS_V6_MAC_ADDRESS), 1295 (short) ETH_P_IPV6); 1296 builder.writeIpv6Header(0x680515ca /* vtf */, (byte) IPPROTO_UDP, (short) 0 /* hopLimit */, 1297 (Inet6Address) InetAddress.getByAddress(IPV6_ANOTHER_ADDR), 1298 (Inet6Address) Inet6Address.getByAddress(IPV6_MDNS_MULTICAST_ADDR)); 1299 builder.writeUdpHeader((short) MDNS_UDP_PORT, (short) MDNS_UDP_PORT); 1300 fillQuestionSection(buf, qnames); 1301 return builder.finalizePacket().array(); 1302 } 1303 putLabel(ByteBuffer buf, String label)1304 private static void putLabel(ByteBuffer buf, String label) { 1305 final byte[] bytes = label.getBytes(StandardCharsets.UTF_8); 1306 buf.put((byte) bytes.length); 1307 buf.put(bytes); 1308 } 1309 putPointer(ByteBuffer buf, int offset)1310 private static void putPointer(ByteBuffer buf, int offset) { 1311 short pointer = (short) (offset | 0xc000); 1312 buf.putShort(pointer); 1313 } 1314 1315 1316 // Simplistic DNS compression code that intentionally does not depend on production code. getDnsLabels(int startOffset, String... names)1317 private static List<Pair<Integer, String>> getDnsLabels(int startOffset, String... names) { 1318 // Maps all possible name suffixes to packet offsets. 1319 final HashMap<String, Integer> mPointerOffsets = new HashMap<>(); 1320 final List<Pair<Integer, String>> out = new ArrayList<>(); 1321 int offset = startOffset; 1322 for (int i = 0; i < names.length; i++) { 1323 String name = names[i]; 1324 while (true) { 1325 if (name.length() == 0) { 1326 out.add(label("")); 1327 offset += 1 + 4; // 1-byte label, DNS query 1328 break; 1329 } 1330 1331 final int pointerOffset = mPointerOffsets.getOrDefault(name, -1); 1332 if (pointerOffset != -1) { 1333 out.add(pointer(pointerOffset)); 1334 offset += 2 + 4; // 2-byte pointer, DNS query 1335 break; 1336 } 1337 1338 mPointerOffsets.put(name, offset); 1339 1340 final int indexOfDot = name.indexOf("."); 1341 final String label; 1342 if (indexOfDot == -1) { 1343 label = name; 1344 name = ""; 1345 } else { 1346 label = name.substring(0, indexOfDot); 1347 name = name.substring(indexOfDot + 1); 1348 } 1349 out.add(label(label)); 1350 offset += 1 + label.length(); 1351 } 1352 } 1353 return out; 1354 } 1355 label(String label)1356 static Pair<Integer, String> label(String label) { 1357 return Pair.create(label.length(), label); 1358 } 1359 pointer(int offset)1360 static Pair<Integer, String> pointer(int offset) { 1361 return Pair.create(0xc000 | offset, null); 1362 } 1363 1364 @Test testGetDnsLabels()1365 public void testGetDnsLabels() throws Exception { 1366 int startOffset = 12; 1367 List<Pair<Integer, String>> actual = getDnsLabels(startOffset, "myservice.tcp.local"); 1368 assertEquals(4, actual.size()); 1369 assertEquals(label("myservice"), actual.get(0)); 1370 assertEquals(label("tcp"), actual.get(1)); 1371 assertEquals(label("local"), actual.get(2)); 1372 assertEquals(label(""), actual.get(3)); 1373 1374 startOffset = 30; 1375 actual = getDnsLabels(startOffset, 1376 "myservice.tcp.local", "foo.tcp.local", "myhostname.local", "bar.udp.local", 1377 "foo.myhostname.local"); 1378 final int tcpLocalOffset = startOffset + 1 + "myservice".length(); 1379 final int localOffset = startOffset + 1 + "myservice".length() + 1 + "tcp".length(); 1380 final int myhostnameLocalOffset = 30 1381 + 1 + "myservice".length() + 1 + "tcp".length() + 1 + "local".length() + 1 + 4 1382 + 1 + "foo".length() + 2 + 4; 1383 1384 assertEquals(13, actual.size()); 1385 assertEquals(label("myservice"), actual.get(0)); 1386 assertEquals(label("tcp"), actual.get(1)); 1387 assertEquals(label("local"), actual.get(2)); 1388 assertEquals(label(""), actual.get(3)); 1389 assertEquals(label("foo"), actual.get(4)); 1390 assertEquals(pointer(tcpLocalOffset), actual.get(5)); 1391 assertEquals(label("myhostname"), actual.get(6)); 1392 assertEquals(pointer(localOffset), actual.get(7)); 1393 assertEquals(label("bar"), actual.get(8)); 1394 assertEquals(label("udp"), actual.get(9)); 1395 assertEquals(pointer(localOffset), actual.get(10)); 1396 assertEquals(label("foo"), actual.get(11)); 1397 assertEquals(pointer(myhostnameLocalOffset), actual.get(12)); 1398 1399 } 1400 makeMdnsCompressedV6Packet(String... names)1401 private static byte[] makeMdnsCompressedV6Packet(String... names) throws IOException { 1402 ByteBuffer questions = ByteBuffer.allocate(1500); 1403 questions.put(new DnsPacket.DnsHeader(123, 0, names.length, 0).getBytes()); 1404 final List<Pair<Integer, String>> labels = getDnsLabels(questions.position(), names); 1405 for (Pair<Integer, String> label : labels) { 1406 final String name = label.second; 1407 if (name == null) { 1408 putPointer(questions, label.first); 1409 } else { 1410 putLabel(questions, name); 1411 } 1412 if (TextUtils.isEmpty(name)) { 1413 questions.put(new byte[4]); 1414 } 1415 } 1416 questions.flip(); 1417 1418 ByteBuffer buf = PacketBuilder.allocate(/*hasEther=*/ true, IPPROTO_IPV6, IPPROTO_UDP, 1419 questions.limit()); 1420 final PacketBuilder builder = new PacketBuilder(buf); 1421 builder.writeL2Header(MacAddress.fromString("11:22:33:44:55:66"), 1422 MacAddress.fromBytes(ETH_MULTICAST_MDNS_V6_MAC_ADDRESS), 1423 (short) ETH_P_IPV6); 1424 builder.writeIpv6Header(0x680515ca /* vtf */, (byte) IPPROTO_UDP, (short) 0 /* hopLimit */, 1425 (Inet6Address) InetAddress.getByAddress(IPV6_ANOTHER_ADDR), 1426 (Inet6Address) Inet6Address.getByAddress(IPV6_MDNS_MULTICAST_ADDR)); 1427 builder.writeUdpHeader((short) MDNS_UDP_PORT, (short) MDNS_UDP_PORT); 1428 1429 buf.put(questions); 1430 1431 return builder.finalizePacket().array(); 1432 } 1433 makeMdnsCompressedV6Packet()1434 private static byte[] makeMdnsCompressedV6Packet() throws IOException { 1435 return makeMdnsCompressedV6Packet("myservice.tcp.local", "googlecast.tcp.local", 1436 "matter.tcp.local", "myhostname.local"); 1437 } 1438 makeMdnsCompressedV6PacketWithManyNames()1439 private static byte[] makeMdnsCompressedV6PacketWithManyNames() throws IOException { 1440 return makeMdnsCompressedV6Packet("myservice.tcp.local", "googlecast.tcp.local", 1441 "matter.tcp.local", "myhostname.local", "myhostname2.local", "myhostname3.local", 1442 "myhostname4.local", "myhostname5.local", "myhostname6.local", "myhostname7.local"); 1443 1444 } 1445 1446 @Test testAddNopAddsOneByte()1447 public void testAddNopAddsOneByte() throws Exception { 1448 ApfV4Generator gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 1449 gen.addNop(); 1450 assertEquals(1, gen.generate().length); 1451 1452 final int count = 42; 1453 gen = new ApfV4Generator(APF_VERSION_2, mRamSize, mClampSize); 1454 for (int i = 0; i < count; i++) { 1455 gen.addNop(); 1456 } 1457 assertEquals(count, gen.generate().length); 1458 } 1459 1460 @Test testApfFilterMulticast()1461 public void testApfFilterMulticast() throws Exception { 1462 final byte[] unicastIpv4Addr = {(byte)192,0,2,63}; 1463 final byte[] broadcastIpv4Addr = {(byte)192,0,2,(byte)255}; 1464 final byte[] multicastIpv4Addr = {(byte)224,0,0,1}; 1465 final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb}; 1466 1467 LinkAddress link = new LinkAddress(InetAddress.getByAddress(unicastIpv4Addr), 24); 1468 LinkProperties lp = new LinkProperties(); 1469 lp.addLinkAddress(link); 1470 1471 ApfConfiguration config = getDefaultConfig(); 1472 config.ieee802_3Filter = DROP_802_3_FRAMES; 1473 final ApfFilter apfFilter = getApfFilter(config); 1474 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 1475 apfFilter.setLinkProperties(lp); 1476 1477 byte[] program = 1478 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 1479 1480 // Construct IPv4 and IPv6 multicast packets. 1481 ByteBuffer mcastv4packet = makeIpv4Packet(IPPROTO_UDP); 1482 put(mcastv4packet, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr); 1483 1484 ByteBuffer mcastv6packet = makeIpv6Packet(IPPROTO_UDP); 1485 put(mcastv6packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr); 1486 1487 // Construct IPv4 broadcast packet. 1488 ByteBuffer bcastv4packet1 = makeIpv4Packet(IPPROTO_UDP); 1489 bcastv4packet1.put(ETH_BROADCAST_MAC_ADDRESS); 1490 bcastv4packet1.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 1491 put(bcastv4packet1, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr); 1492 1493 ByteBuffer bcastv4packet2 = makeIpv4Packet(IPPROTO_UDP); 1494 bcastv4packet2.put(ETH_BROADCAST_MAC_ADDRESS); 1495 bcastv4packet2.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 1496 put(bcastv4packet2, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS); 1497 1498 // Construct IPv4 broadcast with L2 unicast address packet (b/30231088). 1499 ByteBuffer bcastv4unicastl2packet = makeIpv4Packet(IPPROTO_UDP); 1500 bcastv4unicastl2packet.put(TEST_MAC_ADDR); 1501 bcastv4unicastl2packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); 1502 put(bcastv4unicastl2packet, IPV4_DEST_ADDR_OFFSET, broadcastIpv4Addr); 1503 1504 // Verify initially disabled multicast filter is off 1505 assertPass(program, mcastv4packet.array()); 1506 assertPass(program, mcastv6packet.array()); 1507 assertPass(program, bcastv4packet1.array()); 1508 assertPass(program, bcastv4packet2.array()); 1509 assertPass(program, bcastv4unicastl2packet.array()); 1510 1511 // Turn on multicast filter and verify it works 1512 apfFilter.setMulticastFilter(true); 1513 program = mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 1514 assertDrop(program, mcastv4packet.array()); 1515 assertDrop(program, mcastv6packet.array()); 1516 assertDrop(program, bcastv4packet1.array()); 1517 assertDrop(program, bcastv4packet2.array()); 1518 assertDrop(program, bcastv4unicastl2packet.array()); 1519 1520 // Turn off multicast filter and verify it's off 1521 apfFilter.setMulticastFilter(false); 1522 program = mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 1523 assertPass(program, mcastv4packet.array()); 1524 assertPass(program, mcastv6packet.array()); 1525 assertPass(program, bcastv4packet1.array()); 1526 assertPass(program, bcastv4packet2.array()); 1527 assertPass(program, bcastv4unicastl2packet.array()); 1528 1529 // Verify it can be initialized to on 1530 config.multicastFilter = DROP_MULTICAST; 1531 config.ieee802_3Filter = DROP_802_3_FRAMES; 1532 clearInvocations(mApfController); 1533 final ApfFilter apfFilter2 = getApfFilter(config); 1534 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 1535 apfFilter2.setLinkProperties(lp); 1536 program = mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 1537 assertDrop(program, mcastv4packet.array()); 1538 assertDrop(program, mcastv6packet.array()); 1539 assertDrop(program, bcastv4packet1.array()); 1540 assertDrop(program, bcastv4unicastl2packet.array()); 1541 1542 // Verify that ICMPv6 multicast is not dropped. 1543 mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6); 1544 assertPass(program, mcastv6packet.array()); 1545 } 1546 1547 @Test testApfFilterMulticastPingWhileDozing()1548 public void testApfFilterMulticastPingWhileDozing() throws Exception { 1549 doTestApfFilterMulticastPingWhileDozing(false /* isLightDozing */); 1550 } 1551 1552 @Test 1553 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) testApfFilterMulticastPingWhileLightDozing()1554 public void testApfFilterMulticastPingWhileLightDozing() throws Exception { 1555 doTestApfFilterMulticastPingWhileDozing(true /* isLightDozing */); 1556 } 1557 doTestApfFilterMulticastPingWhileDozing(boolean isLightDozing)1558 private void doTestApfFilterMulticastPingWhileDozing(boolean isLightDozing) throws Exception { 1559 final ApfConfiguration configuration = getDefaultConfig(); 1560 final ApfFilter apfFilter = getApfFilter(configuration); 1561 byte[] program = 1562 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 1563 final ArgumentCaptor<BroadcastReceiver> receiverCaptor = 1564 ArgumentCaptor.forClass(BroadcastReceiver.class); 1565 verify(mDependencies).addDeviceIdleReceiver(receiverCaptor.capture()); 1566 final BroadcastReceiver receiver = receiverCaptor.getValue(); 1567 1568 // Construct a multicast ICMPv6 ECHO request. 1569 final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb}; 1570 final ByteBuffer packet = makeIpv6Packet(IPPROTO_ICMPV6); 1571 packet.put(ICMP6_TYPE_OFFSET, (byte)ICMPV6_ECHO_REQUEST_TYPE); 1572 put(packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr); 1573 1574 // Normally, we let multicast pings alone... 1575 assertPass(program, packet.array()); 1576 1577 if (isLightDozing) { 1578 doReturn(true).when(mPowerManager).isDeviceLightIdleMode(); 1579 receiver.onReceive(mContext, new Intent(ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED)); 1580 } else { 1581 doReturn(true).when(mPowerManager).isDeviceIdleMode(); 1582 receiver.onReceive(mContext, new Intent(ACTION_DEVICE_IDLE_MODE_CHANGED)); 1583 } 1584 program = mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 1585 // ...and even while dozing... 1586 assertPass(program, packet.array()); 1587 1588 // ...but when the multicast filter is also enabled, drop the multicast pings to save power. 1589 apfFilter.setMulticastFilter(true); 1590 program = mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 1591 assertDrop(program, packet.array()); 1592 1593 // However, we should still let through all other ICMPv6 types. 1594 ByteBuffer raPacket = ByteBuffer.wrap(packet.array().clone()); 1595 setIpv6VersionFields(packet); 1596 packet.put(IPV6_NEXT_HEADER_OFFSET, (byte) IPPROTO_ICMPV6); 1597 raPacket.put(ICMP6_TYPE_OFFSET, (byte) NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT); 1598 assertPass(program, raPacket.array()); 1599 1600 // Now wake up from doze mode to ensure that we no longer drop the packets. 1601 // (The multicast filter is still enabled at this point). 1602 if (isLightDozing) { 1603 doReturn(false).when(mPowerManager).isDeviceLightIdleMode(); 1604 receiver.onReceive(mContext, new Intent(ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED)); 1605 } else { 1606 doReturn(false).when(mPowerManager).isDeviceIdleMode(); 1607 receiver.onReceive(mContext, new Intent(ACTION_DEVICE_IDLE_MODE_CHANGED)); 1608 } 1609 program = mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 1610 assertPass(program, packet.array()); 1611 } 1612 1613 @Test 1614 @DevSdkIgnoreRule.IgnoreAfter(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) testApfFilter802_3()1615 public void testApfFilter802_3() throws Exception { 1616 ApfConfiguration config = getDefaultConfig(); 1617 ApfFilter apfFilter = getApfFilter(config); 1618 byte[] program = 1619 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 1620 1621 // Verify empty packet of 100 zero bytes is passed 1622 // Note that eth-type = 0 makes it an IEEE802.3 frame 1623 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1624 assertPass(program, packet.array()); 1625 1626 // Verify empty packet with IPv4 is passed 1627 setIpv4VersionFields(packet); 1628 assertPass(program, packet.array()); 1629 1630 // Verify empty IPv6 packet is passed 1631 setIpv6VersionFields(packet); 1632 assertPass(program, packet.array()); 1633 1634 // Now turn on the filter 1635 config.ieee802_3Filter = DROP_802_3_FRAMES; 1636 apfFilter = getApfFilter(config); 1637 program = mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 1638 1639 // Verify that IEEE802.3 frame is dropped 1640 // In this case ethtype is used for payload length 1641 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)(100 - 14)); 1642 assertDrop(program, packet.array()); 1643 1644 // Verify that IPv4 (as example of Ethernet II) frame will pass 1645 setIpv4VersionFields(packet); 1646 assertPass(program, packet.array()); 1647 1648 // Verify that IPv6 (as example of Ethernet II) frame will pass 1649 setIpv6VersionFields(packet); 1650 assertPass(program, packet.array()); 1651 } 1652 1653 @Test 1654 @DevSdkIgnoreRule.IgnoreAfter(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) testApfFilterEthTypeBL()1655 public void testApfFilterEthTypeBL() throws Exception { 1656 final int[] emptyBlackList = {}; 1657 final int[] ipv4BlackList = {ETH_P_IP}; 1658 final int[] ipv4Ipv6BlackList = {ETH_P_IP, ETH_P_IPV6}; 1659 1660 ApfConfiguration config = getDefaultConfig(); 1661 ApfFilter apfFilter = getApfFilter(config); 1662 byte[] program = 1663 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 1664 1665 // Verify empty packet of 100 zero bytes is passed 1666 // Note that eth-type = 0 makes it an IEEE802.3 frame 1667 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1668 assertPass(program, packet.array()); 1669 1670 // Verify empty packet with IPv4 is passed 1671 setIpv4VersionFields(packet); 1672 assertPass(program, packet.array()); 1673 1674 // Verify empty IPv6 packet is passed 1675 setIpv6VersionFields(packet); 1676 assertPass(program, packet.array()); 1677 1678 // Now add IPv4 to the black list 1679 config.ethTypeBlackList = ipv4BlackList; 1680 apfFilter = getApfFilter(config); 1681 program = mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 1682 1683 // Verify that IPv4 frame will be dropped 1684 setIpv4VersionFields(packet); 1685 assertDrop(program, packet.array()); 1686 1687 // Verify that IPv6 frame will pass 1688 setIpv6VersionFields(packet); 1689 assertPass(program, packet.array()); 1690 1691 // Now let us have both IPv4 and IPv6 in the black list 1692 config.ethTypeBlackList = ipv4Ipv6BlackList; 1693 apfFilter = getApfFilter(config); 1694 program = mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 1695 1696 // Verify that IPv4 frame will be dropped 1697 setIpv4VersionFields(packet); 1698 assertDrop(program, packet.array()); 1699 1700 // Verify that IPv6 frame will be dropped 1701 setIpv6VersionFields(packet); 1702 assertDrop(program, packet.array()); 1703 } 1704 verifyArpFilter(byte[] program, int filterResult)1705 private void verifyArpFilter(byte[] program, int filterResult) { 1706 // Verify ARP request packet 1707 assertPass(program, arpRequestBroadcast(MOCK_IPV4_ADDR)); 1708 assertVerdict(filterResult, program, arpRequestBroadcast(ANOTHER_IPV4_ADDR)); 1709 assertVerdict(filterResult, program, arpRequestBroadcast(IPV4_ANY_HOST_ADDR)); 1710 1711 // Verify ARP reply packets from different source ip 1712 assertDrop(program, arpReply(IPV4_ANY_HOST_ADDR, IPV4_ANY_HOST_ADDR)); 1713 assertPass(program, arpReply(ANOTHER_IPV4_SOURCE_ADDR, IPV4_ANY_HOST_ADDR)); 1714 assertPass(program, arpReply(BUG_PROBE_SOURCE_ADDR1, IPV4_ANY_HOST_ADDR)); 1715 assertPass(program, arpReply(BUG_PROBE_SOURCE_ADDR2, IPV4_ANY_HOST_ADDR)); 1716 1717 // Verify unicast ARP reply packet is always accepted. 1718 assertPass(program, arpReply(IPV4_SOURCE_ADDR, MOCK_IPV4_ADDR)); 1719 assertPass(program, arpReply(IPV4_SOURCE_ADDR, ANOTHER_IPV4_ADDR)); 1720 assertPass(program, arpReply(IPV4_SOURCE_ADDR, IPV4_ANY_HOST_ADDR)); 1721 1722 // Verify GARP reply packets are always filtered 1723 assertDrop(program, garpReply()); 1724 } 1725 1726 @Test testApfFilterArp()1727 public void testApfFilterArp() throws Exception { 1728 ApfConfiguration config = getDefaultConfig(); 1729 config.multicastFilter = DROP_MULTICAST; 1730 config.ieee802_3Filter = DROP_802_3_FRAMES; 1731 ApfFilter apfFilter = getApfFilter(config); 1732 byte[] program = 1733 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 1734 1735 // Verify initially ARP request filter is off, and GARP filter is on. 1736 verifyArpFilter(program, PASS); 1737 1738 // Inform ApfFilter of our address and verify ARP filtering is on 1739 LinkAddress linkAddress = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 24); 1740 LinkProperties lp = new LinkProperties(); 1741 assertTrue(lp.addLinkAddress(linkAddress)); 1742 apfFilter.setLinkProperties(lp); 1743 program = mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 1744 verifyArpFilter(program, DROP); 1745 1746 apfFilter.setLinkProperties(new LinkProperties()); 1747 program = mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 1748 // Inform ApfFilter of loss of IP and verify ARP filtering is off 1749 verifyArpFilter(program, PASS); 1750 } 1751 arpReply(byte[] sip, byte[] tip)1752 private static byte[] arpReply(byte[] sip, byte[] tip) { 1753 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1754 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP); 1755 put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER); 1756 put(packet, ARP_SOURCE_IP_ADDRESS_OFFSET, sip); 1757 put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip); 1758 return packet.array(); 1759 } 1760 arpRequestBroadcast(byte[] tip)1761 private static byte[] arpRequestBroadcast(byte[] tip) { 1762 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1763 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP); 1764 put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS); 1765 put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REQUEST_HEADER); 1766 put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip); 1767 return packet.array(); 1768 } 1769 garpReply()1770 private static byte[] garpReply() { 1771 ByteBuffer packet = ByteBuffer.wrap(new byte[100]); 1772 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP); 1773 put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS); 1774 put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER); 1775 put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, IPV4_ANY_HOST_ADDR); 1776 return packet.array(); 1777 } 1778 1779 private static final byte[] IPV6_ANOTHER_ADDR = 1780 {(byte) 0x24, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xfa, (byte) 0xf5}; 1781 1782 private static class RaPacketBuilder { 1783 final ByteArrayOutputStream mPacket = new ByteArrayOutputStream(); 1784 int mFlowLabel = 0x12345; 1785 int mReachableTime = 30_000; 1786 int mRetransmissionTimer = 1000; 1787 RaPacketBuilder(int routerLft)1788 public RaPacketBuilder(int routerLft) throws Exception { 1789 InetAddress src = InetAddress.getByName("fe80::1234:abcd"); 1790 ByteBuffer buffer = ByteBuffer.allocate(ICMP6_RA_OPTION_OFFSET); 1791 1792 buffer.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IPV6); 1793 buffer.position(ETH_HEADER_LEN); 1794 1795 // skip version, tclass, flowlabel; set in build() 1796 buffer.position(buffer.position() + 4); 1797 1798 buffer.putShort((short) 0); // Payload length; updated later 1799 buffer.put((byte) IPPROTO_ICMPV6); // Next header 1800 buffer.put((byte) 0xff); // Hop limit 1801 buffer.put(src.getAddress()); // Source address 1802 buffer.put(IPV6_ALL_NODES_ADDRESS); // Destination address 1803 1804 buffer.put((byte) ICMP6_ROUTER_ADVERTISEMENT); // Type 1805 buffer.put((byte) 0); // Code (0) 1806 buffer.putShort((short) 0); // Checksum (ignored) 1807 buffer.put((byte) 64); // Hop limit 1808 buffer.put((byte) 0); // M/O, reserved 1809 buffer.putShort((short) routerLft); // Router lifetime 1810 // skip reachable time; set in build() 1811 // skip retransmission timer; set in build(); 1812 1813 mPacket.write(buffer.array(), 0, buffer.capacity()); 1814 } 1815 setFlowLabel(int flowLabel)1816 public RaPacketBuilder setFlowLabel(int flowLabel) { 1817 mFlowLabel = flowLabel; 1818 return this; 1819 } 1820 setReachableTime(int reachable)1821 public RaPacketBuilder setReachableTime(int reachable) { 1822 mReachableTime = reachable; 1823 return this; 1824 } 1825 setRetransmissionTimer(int retrans)1826 public RaPacketBuilder setRetransmissionTimer(int retrans) { 1827 mRetransmissionTimer = retrans; 1828 return this; 1829 } 1830 addPioOption(int valid, int preferred, String prefixString)1831 public RaPacketBuilder addPioOption(int valid, int preferred, String prefixString) 1832 throws Exception { 1833 ByteBuffer buffer = ByteBuffer.allocate(ICMP6_PREFIX_OPTION_LEN); 1834 1835 IpPrefix prefix = new IpPrefix(prefixString); 1836 buffer.put((byte) ICMP6_PREFIX_OPTION_TYPE); // Type 1837 buffer.put((byte) 4); // Length in 8-byte units 1838 buffer.put((byte) prefix.getPrefixLength()); // Prefix length 1839 buffer.put((byte) 0b11000000); // L = 1, A = 1 1840 buffer.putInt(valid); 1841 buffer.putInt(preferred); 1842 buffer.putInt(0); // Reserved 1843 buffer.put(prefix.getRawAddress()); 1844 1845 mPacket.write(buffer.array(), 0, buffer.capacity()); 1846 return this; 1847 } 1848 addRioOption(int lifetime, String prefixString)1849 public RaPacketBuilder addRioOption(int lifetime, String prefixString) throws Exception { 1850 IpPrefix prefix = new IpPrefix(prefixString); 1851 1852 int optionLength; 1853 if (prefix.getPrefixLength() == 0) { 1854 optionLength = 1; 1855 } else if (prefix.getPrefixLength() <= 64) { 1856 optionLength = 2; 1857 } else { 1858 optionLength = 3; 1859 } 1860 1861 ByteBuffer buffer = ByteBuffer.allocate(optionLength * 8); 1862 1863 buffer.put((byte) ICMP6_ROUTE_INFO_OPTION_TYPE); // Type 1864 buffer.put((byte) optionLength); // Length in 8-byte units 1865 buffer.put((byte) prefix.getPrefixLength()); // Prefix length 1866 buffer.put((byte) 0b00011000); // Pref = high 1867 buffer.putInt(lifetime); // Lifetime 1868 1869 byte[] prefixBytes = prefix.getRawAddress(); 1870 buffer.put(prefixBytes, 0, (optionLength - 1) * 8); 1871 1872 mPacket.write(buffer.array(), 0, buffer.capacity()); 1873 return this; 1874 } 1875 addDnsslOption(int lifetime, String... domains)1876 public RaPacketBuilder addDnsslOption(int lifetime, String... domains) { 1877 ByteArrayOutputStream dnssl = new ByteArrayOutputStream(); 1878 for (String domain : domains) { 1879 for (String label : domain.split("\\.")) { 1880 final byte[] bytes = label.getBytes(StandardCharsets.UTF_8); 1881 dnssl.write((byte) bytes.length); 1882 dnssl.write(bytes, 0, bytes.length); 1883 } 1884 dnssl.write((byte) 0); 1885 } 1886 1887 // Extend with 0s to make it 8-byte aligned. 1888 while (dnssl.size() % 8 != 0) { 1889 dnssl.write((byte) 0); 1890 } 1891 1892 final int length = ICMP6_4_BYTE_OPTION_LEN + dnssl.size(); 1893 ByteBuffer buffer = ByteBuffer.allocate(length); 1894 1895 buffer.put((byte) ICMP6_DNSSL_OPTION_TYPE); // Type 1896 buffer.put((byte) (length / 8)); // Length 1897 // skip past reserved bytes 1898 buffer.position(buffer.position() + 2); 1899 buffer.putInt(lifetime); // Lifetime 1900 buffer.put(dnssl.toByteArray()); // Domain names 1901 1902 mPacket.write(buffer.array(), 0, buffer.capacity()); 1903 return this; 1904 } 1905 addRdnssOption(int lifetime, String... servers)1906 public RaPacketBuilder addRdnssOption(int lifetime, String... servers) throws Exception { 1907 int optionLength = 1 + 2 * servers.length; // In 8-byte units 1908 ByteBuffer buffer = ByteBuffer.allocate(optionLength * 8); 1909 1910 buffer.put((byte) ICMP6_RDNSS_OPTION_TYPE); // Type 1911 buffer.put((byte) optionLength); // Length 1912 buffer.putShort((short) 0); // Reserved 1913 buffer.putInt(lifetime); // Lifetime 1914 for (String server : servers) { 1915 buffer.put(InetAddress.getByName(server).getAddress()); 1916 } 1917 1918 mPacket.write(buffer.array(), 0, buffer.capacity()); 1919 return this; 1920 } 1921 addZeroLengthOption()1922 public RaPacketBuilder addZeroLengthOption() throws Exception { 1923 ByteBuffer buffer = ByteBuffer.allocate(ICMP6_4_BYTE_OPTION_LEN); 1924 buffer.put((byte) ICMP6_PREFIX_OPTION_TYPE); 1925 buffer.put((byte) 0); 1926 1927 mPacket.write(buffer.array(), 0, buffer.capacity()); 1928 return this; 1929 } 1930 build()1931 public byte[] build() { 1932 ByteBuffer buffer = ByteBuffer.wrap(mPacket.toByteArray()); 1933 // IPv6, traffic class = 0, flow label = mFlowLabel 1934 buffer.putInt(IP_HEADER_OFFSET, 0x60000000 | (0xFFFFF & mFlowLabel)); 1935 buffer.putShort(IPV6_PAYLOAD_LENGTH_OFFSET, (short) buffer.capacity()); 1936 1937 buffer.position(ICMP6_RA_REACHABLE_TIME_OFFSET); 1938 buffer.putInt(mReachableTime); 1939 buffer.putInt(mRetransmissionTimer); 1940 1941 return buffer.array(); 1942 } 1943 } 1944 buildLargeRa()1945 private byte[] buildLargeRa() throws Exception { 1946 RaPacketBuilder builder = new RaPacketBuilder(1800 /* router lft */); 1947 1948 builder.addRioOption(1200, "64:ff9b::/96"); 1949 builder.addRdnssOption(7200, "2001:db8:1::1", "2001:db8:1::2"); 1950 builder.addRioOption(2100, "2000::/3"); 1951 builder.addRioOption(2400, "::/0"); 1952 builder.addPioOption(600, 300, "2001:db8:a::/64"); 1953 builder.addRioOption(1500, "2001:db8:c:d::/64"); 1954 builder.addPioOption(86400, 43200, "fd95:d1e:12::/64"); 1955 1956 return builder.build(); 1957 } 1958 1959 @Test testRaToString()1960 public void testRaToString() throws Exception { 1961 ApfConfiguration config = getDefaultConfig(); 1962 ApfFilter apfFilter = getApfFilter(config); 1963 1964 byte[] packet = buildLargeRa(); 1965 ApfFilter.Ra ra = apfFilter.new Ra(packet, packet.length); 1966 String expected = "RA fe80::1234:abcd -> ff02::1 1800s " 1967 + "2001:db8:a::/64 600s/300s fd95:d1e:12::/64 86400s/43200s " 1968 + "DNS 7200s 2001:db8:1::1 2001:db8:1::2 " 1969 + "RIO 1200s 64:ff9b::/96 RIO 2100s 2000::/3 " 1970 + "RIO 2400s ::/0 RIO 1500s 2001:db8:c:d::/64 "; 1971 assertEquals(expected, ra.toString()); 1972 } 1973 1974 // Verify that the last program pushed to the IpClient.Callback properly filters the 1975 // given packet for the given lifetime. verifyRaLifetime(byte[] program, ByteBuffer packet, int lifetime)1976 private void verifyRaLifetime(byte[] program, ByteBuffer packet, int lifetime) { 1977 verifyRaLifetime(program, packet, lifetime, 0); 1978 } 1979 1980 // Verify that the last program pushed to the IpClient.Callback properly filters the 1981 // given packet for the given lifetime and programInstallTime. programInstallTime is 1982 // the time difference between when RA is last seen and the program is installed. verifyRaLifetime(byte[] program, ByteBuffer packet, int lifetime, int programInstallTime)1983 private void verifyRaLifetime(byte[] program, ByteBuffer packet, int lifetime, 1984 int programInstallTime) { 1985 final int FRACTION_OF_LIFETIME = 6; 1986 final int ageLimit = lifetime / FRACTION_OF_LIFETIME - programInstallTime; 1987 1988 // Verify new program should drop RA for 1/6th its lifetime and pass afterwards. 1989 assertDrop(program, packet.array()); 1990 assertDrop(program, packet.array(), ageLimit); 1991 assertPass(program, packet.array(), ageLimit + 1); 1992 assertPass(program, packet.array(), lifetime); 1993 // Verify RA checksum is ignored 1994 final short originalChecksum = packet.getShort(ICMP6_RA_CHECKSUM_OFFSET); 1995 packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)12345); 1996 assertDrop(program, packet.array()); 1997 packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)-12345); 1998 assertDrop(program, packet.array()); 1999 packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, originalChecksum); 2000 2001 // Verify other changes to RA (e.g., a change in the source address) make it not match. 2002 final int offset = IPV6_SRC_ADDR_OFFSET + 5; 2003 final byte originalByte = packet.get(offset); 2004 packet.put(offset, (byte) (~originalByte)); 2005 assertPass(program, packet.array()); 2006 packet.put(offset, originalByte); 2007 assertDrop(program, packet.array()); 2008 } 2009 2010 // Test that when ApfFilter is shown the given packet, it generates a program to filter it 2011 // for the given lifetime. verifyRaLifetime(ByteBuffer packet, int lifetime)2012 private byte[] verifyRaLifetime(ByteBuffer packet, int lifetime) 2013 throws IOException, ErrnoException { 2014 // Verify new program generated if ApfFilter witnesses RA 2015 clearInvocations(mApfController); 2016 pretendPacketReceived(packet.array()); 2017 byte[] program = 2018 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2019 verifyRaLifetime(program, packet, lifetime); 2020 return program; 2021 } 2022 assertInvalidRa(ByteBuffer packet)2023 private void assertInvalidRa(ByteBuffer packet) 2024 throws IOException, ErrnoException, InterruptedException { 2025 clearInvocations(mApfController); 2026 pretendPacketReceived(packet.array()); 2027 Thread.sleep(NO_CALLBACK_TIMEOUT_MS); 2028 verify(mApfController, never()).installPacketFilter(any(), any()); 2029 } 2030 2031 @Test testApfFilterRa()2032 public void testApfFilterRa() throws Exception { 2033 ApfConfiguration config = getDefaultConfig(); 2034 config.multicastFilter = DROP_MULTICAST; 2035 config.ieee802_3Filter = DROP_802_3_FRAMES; 2036 ApfFilter apfFilter = getApfFilter(config); 2037 byte[] program = 2038 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2039 2040 final int ROUTER_LIFETIME = 1000; 2041 final int PREFIX_VALID_LIFETIME = 200; 2042 final int PREFIX_PREFERRED_LIFETIME = 100; 2043 final int RDNSS_LIFETIME = 300; 2044 final int ROUTE_LIFETIME = 400; 2045 // Note that lifetime of 2000 will be ignored in favor of shorter route lifetime of 1000. 2046 final int DNSSL_LIFETIME = 2000; 2047 2048 // Verify RA is passed the first time 2049 RaPacketBuilder ra = new RaPacketBuilder(ROUTER_LIFETIME); 2050 ByteBuffer basePacket = ByteBuffer.wrap(ra.build()); 2051 assertPass(program, basePacket.array()); 2052 2053 verifyRaLifetime(basePacket, ROUTER_LIFETIME); 2054 2055 ra = new RaPacketBuilder(ROUTER_LIFETIME); 2056 // Check that changes are ignored in every byte of the flow label. 2057 ra.setFlowLabel(0x56789); 2058 ByteBuffer newFlowLabelPacket = ByteBuffer.wrap(ra.build()); 2059 2060 // Ensure zero-length options cause the packet to be silently skipped. 2061 // Do this before we test other packets. http://b/29586253 2062 ra = new RaPacketBuilder(ROUTER_LIFETIME); 2063 ra.addZeroLengthOption(); 2064 ByteBuffer zeroLengthOptionPacket = ByteBuffer.wrap(ra.build()); 2065 assertInvalidRa(zeroLengthOptionPacket); 2066 2067 // Generate several RAs with different options and lifetimes, and verify when 2068 // ApfFilter is shown these packets, it generates programs to filter them for the 2069 // appropriate lifetime. 2070 ra = new RaPacketBuilder(ROUTER_LIFETIME); 2071 ra.addPioOption(PREFIX_VALID_LIFETIME, PREFIX_PREFERRED_LIFETIME, "2001:db8::/64"); 2072 ByteBuffer prefixOptionPacket = ByteBuffer.wrap(ra.build()); 2073 verifyRaLifetime(prefixOptionPacket, PREFIX_PREFERRED_LIFETIME); 2074 2075 ra = new RaPacketBuilder(ROUTER_LIFETIME); 2076 ra.addRdnssOption(RDNSS_LIFETIME, "2001:4860:4860::8888", "2001:4860:4860::8844"); 2077 ByteBuffer rdnssOptionPacket = ByteBuffer.wrap(ra.build()); 2078 verifyRaLifetime(rdnssOptionPacket, RDNSS_LIFETIME); 2079 2080 final int lowLifetime = 60; 2081 ra = new RaPacketBuilder(ROUTER_LIFETIME); 2082 ra.addRdnssOption(lowLifetime, "2620:fe::9"); 2083 ByteBuffer lowLifetimeRdnssOptionPacket = ByteBuffer.wrap(ra.build()); 2084 verifyRaLifetime(lowLifetimeRdnssOptionPacket, ROUTER_LIFETIME); 2085 2086 ra = new RaPacketBuilder(ROUTER_LIFETIME); 2087 ra.addRioOption(ROUTE_LIFETIME, "64:ff9b::/96"); 2088 ByteBuffer routeInfoOptionPacket = ByteBuffer.wrap(ra.build()); 2089 program = verifyRaLifetime(routeInfoOptionPacket, ROUTE_LIFETIME); 2090 2091 // Check that RIOs differing only in the first 4 bytes are different. 2092 ra = new RaPacketBuilder(ROUTER_LIFETIME); 2093 ra.addRioOption(ROUTE_LIFETIME, "64:ff9b::/64"); 2094 // Packet should be passed because it is different. 2095 assertPass(program, ra.build()); 2096 2097 ra = new RaPacketBuilder(ROUTER_LIFETIME); 2098 ra.addDnsslOption(DNSSL_LIFETIME, "test.example.com", "one.more.example.com"); 2099 ByteBuffer dnsslOptionPacket = ByteBuffer.wrap(ra.build()); 2100 verifyRaLifetime(dnsslOptionPacket, ROUTER_LIFETIME); 2101 2102 ByteBuffer largeRaPacket = ByteBuffer.wrap(buildLargeRa()); 2103 program = verifyRaLifetime(largeRaPacket, 300); 2104 2105 // Verify that current program filters all the RAs (note: ApfFilter.MAX_RAS == 10). 2106 verifyRaLifetime(program, basePacket, ROUTER_LIFETIME); 2107 verifyRaLifetime(program, newFlowLabelPacket, ROUTER_LIFETIME); 2108 verifyRaLifetime(program, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME); 2109 verifyRaLifetime(program, rdnssOptionPacket, RDNSS_LIFETIME); 2110 verifyRaLifetime(program, lowLifetimeRdnssOptionPacket, ROUTER_LIFETIME); 2111 verifyRaLifetime(program, routeInfoOptionPacket, ROUTE_LIFETIME); 2112 verifyRaLifetime(program, dnsslOptionPacket, ROUTER_LIFETIME); 2113 verifyRaLifetime(program, largeRaPacket, 300); 2114 } 2115 2116 @Test testRaWithDifferentReachableTimeAndRetransTimer()2117 public void testRaWithDifferentReachableTimeAndRetransTimer() throws Exception { 2118 final ApfConfiguration config = getDefaultConfig(); 2119 config.multicastFilter = DROP_MULTICAST; 2120 config.ieee802_3Filter = DROP_802_3_FRAMES; 2121 final ApfFilter apfFilter = getApfFilter(config); 2122 byte[] program = 2123 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2124 final int RA_REACHABLE_TIME = 1800; 2125 final int RA_RETRANSMISSION_TIMER = 1234; 2126 2127 // Create an Ra packet without options 2128 // Reachable time = 1800, retransmission timer = 1234 2129 RaPacketBuilder ra = new RaPacketBuilder(1800 /* router lft */); 2130 ra.setReachableTime(RA_REACHABLE_TIME); 2131 ra.setRetransmissionTimer(RA_RETRANSMISSION_TIMER); 2132 byte[] raPacket = ra.build(); 2133 // First RA passes filter 2134 assertPass(program, raPacket); 2135 2136 // Assume apf is shown the given RA, it generates program to filter it. 2137 pretendPacketReceived(raPacket); 2138 program = mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2139 assertDrop(program, raPacket); 2140 2141 // A packet with different reachable time should be passed. 2142 // Reachable time = 2300, retransmission timer = 1234 2143 ra.setReachableTime(RA_REACHABLE_TIME + 500); 2144 raPacket = ra.build(); 2145 assertPass(program, raPacket); 2146 2147 // A packet with different retransmission timer should be passed. 2148 // Reachable time = 1800, retransmission timer = 2234 2149 ra.setReachableTime(RA_REACHABLE_TIME); 2150 ra.setRetransmissionTimer(RA_RETRANSMISSION_TIMER + 1000); 2151 raPacket = ra.build(); 2152 assertPass(program, raPacket); 2153 } 2154 2155 // The ByteBuffer is always created by ByteBuffer#wrap in the helper functions 2156 @SuppressWarnings("ByteBufferBackingArray") 2157 @Test testRaWithProgramInstalledSomeTimeAfterLastSeen()2158 public void testRaWithProgramInstalledSomeTimeAfterLastSeen() throws Exception { 2159 final ApfConfiguration config = getDefaultConfig(); 2160 config.multicastFilter = DROP_MULTICAST; 2161 config.ieee802_3Filter = DROP_802_3_FRAMES; 2162 final ApfFilter apfFilter = getApfFilter(config); 2163 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2164 2165 final int routerLifetime = 1000; 2166 final int timePassedSeconds = 12; 2167 2168 // Verify that when the program is generated and installed some time after RA is last seen 2169 // it should be installed with the correct remaining lifetime. 2170 ByteBuffer basePacket = ByteBuffer.wrap(new RaPacketBuilder(routerLifetime).build()); 2171 verifyRaLifetime(basePacket, routerLifetime); 2172 2173 mCurrentTimeMs += timePassedSeconds * DateUtils.SECOND_IN_MILLIS; 2174 doReturn(mCurrentTimeMs).when(mDependencies).elapsedRealtime(); 2175 synchronized (apfFilter) { 2176 apfFilter.installNewProgram(); 2177 } 2178 byte[] program = 2179 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2180 verifyRaLifetime(program, basePacket, routerLifetime, timePassedSeconds); 2181 2182 // Packet should be passed if the program is installed after 1/6 * lifetime from last seen 2183 mCurrentTimeMs += 2184 ((routerLifetime / 6) - timePassedSeconds - 1) * DateUtils.SECOND_IN_MILLIS; 2185 doReturn(mCurrentTimeMs).when(mDependencies).elapsedRealtime(); 2186 synchronized (apfFilter) { 2187 apfFilter.installNewProgram(); 2188 } 2189 program = mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2190 assertDrop(program, basePacket.array()); 2191 2192 mCurrentTimeMs += DateUtils.SECOND_IN_MILLIS; 2193 doReturn(mCurrentTimeMs).when(mDependencies).elapsedRealtime(); 2194 synchronized (apfFilter) { 2195 apfFilter.installNewProgram(); 2196 } 2197 program = mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2198 assertPass(program, basePacket.array()); 2199 } 2200 2201 /** 2202 * Stage a file for testing, i.e. make it native accessible. Given a resource ID, 2203 * copy that resource into the app's data directory and return the path to it. 2204 */ stageFile(int rawId)2205 private String stageFile(int rawId) throws Exception { 2206 File file = new File(InstrumentationRegistry.getContext().getFilesDir(), "staged_file"); 2207 new File(file.getParent()).mkdirs(); 2208 InputStream in = null; 2209 OutputStream out = null; 2210 try { 2211 in = InstrumentationRegistry.getContext().getResources().openRawResource(rawId); 2212 out = new FileOutputStream(file); 2213 Streams.copy(in, out); 2214 } finally { 2215 if (in != null) in.close(); 2216 if (out != null) out.close(); 2217 } 2218 return file.getAbsolutePath(); 2219 } 2220 put(ByteBuffer buffer, int position, byte[] bytes)2221 private static void put(ByteBuffer buffer, int position, byte[] bytes) { 2222 final int original = buffer.position(); 2223 buffer.position(position); 2224 buffer.put(bytes); 2225 buffer.position(original); 2226 } 2227 2228 @Test testRaParsing()2229 public void testRaParsing() throws Exception { 2230 final int maxRandomPacketSize = 512; 2231 final Random r = new Random(); 2232 ApfConfiguration config = getDefaultConfig(); 2233 config.multicastFilter = DROP_MULTICAST; 2234 config.ieee802_3Filter = DROP_802_3_FRAMES; 2235 ApfFilter apfFilter = getApfFilter(config); 2236 for (int i = 0; i < 1000; i++) { 2237 byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)]; 2238 r.nextBytes(packet); 2239 try { 2240 apfFilter.new Ra(packet, packet.length); 2241 } catch (ApfFilter.InvalidRaException e) { 2242 } catch (Exception e) { 2243 throw new Exception("bad packet: " + HexDump.toHexString(packet), e); 2244 } 2245 } 2246 } 2247 2248 @Test testRaProcessing()2249 public void testRaProcessing() throws Exception { 2250 final int maxRandomPacketSize = 512; 2251 final Random r = new Random(); 2252 ApfConfiguration config = getDefaultConfig(); 2253 config.multicastFilter = DROP_MULTICAST; 2254 config.ieee802_3Filter = DROP_802_3_FRAMES; 2255 ApfFilter apfFilter = getApfFilter(config); 2256 for (int i = 0; i < 1000; i++) { 2257 byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)]; 2258 r.nextBytes(packet); 2259 try { 2260 apfFilter.processRa(packet, packet.length); 2261 } catch (Exception e) { 2262 throw new Exception("bad packet: " + HexDump.toHexString(packet), e); 2263 } 2264 } 2265 } 2266 2267 @Test testMatchedRaUpdatesLifetime()2268 public void testMatchedRaUpdatesLifetime() throws Exception { 2269 final ApfFilter apfFilter = getApfFilter(getDefaultConfig()); 2270 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2271 2272 // Create an RA and build an APF program 2273 byte[] ra = new RaPacketBuilder(1800 /* router lifetime */).build(); 2274 pretendPacketReceived(ra); 2275 byte[] program = 2276 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2277 2278 // lifetime dropped significantly, assert pass 2279 ra = new RaPacketBuilder(200 /* router lifetime */).build(); 2280 assertPass(program, ra); 2281 2282 // update program with the new RA 2283 pretendPacketReceived(ra); 2284 program = mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2285 2286 // assert program was updated and new lifetimes were taken into account. 2287 assertDrop(program, ra); 2288 } 2289 @Test testProcessRaWithInfiniteLifeTimeWithoutCrash()2290 public void testProcessRaWithInfiniteLifeTimeWithoutCrash() throws Exception { 2291 // configure accept_ra_min_lft 2292 final ApfConfiguration config = getDefaultConfig(); 2293 config.acceptRaMinLft = 180; 2294 ApfFilter apfFilter = getApfFilter(config); 2295 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2296 // Template packet: 2297 // Frame 1: 150 bytes on wire (1200 bits), 150 bytes captured (1200 bits) 2298 // Ethernet II, Src: Netgear_23:67:2c (28:c6:8e:23:67:2c), Dst: IPv6mcast_01 (33:33:00:00:00:01) 2299 // Internet Protocol Version 6, Src: fe80::2ac6:8eff:fe23:672c, Dst: ff02::1 2300 // Internet Control Message Protocol v6 2301 // Type: Router Advertisement (134) 2302 // Code: 0 2303 // Checksum: 0x0acd [correct] 2304 // Checksum Status: Good 2305 // Cur hop limit: 64 2306 // Flags: 0xc0, Managed address configuration, Other configuration, Prf (Default Router Preference): Medium 2307 // Router lifetime (s): 7000 2308 // Reachable time (ms): 0 2309 // Retrans timer (ms): 0 2310 // ICMPv6 Option (Source link-layer address : 28:c6:8e:23:67:2c) 2311 // Type: Source link-layer address (1) 2312 // Length: 1 (8 bytes) 2313 // Link-layer address: Netgear_23:67:2c (28:c6:8e:23:67:2c) 2314 // Source Link-layer address: Netgear_23:67:2c (28:c6:8e:23:67:2c) 2315 // ICMPv6 Option (MTU : 1500) 2316 // Type: MTU (5) 2317 // Length: 1 (8 bytes) 2318 // Reserved 2319 // MTU: 1500 2320 // ICMPv6 Option (Prefix information : 2401:fa00:480:f000::/64) 2321 // Type: Prefix information (3) 2322 // Length: 4 (32 bytes) 2323 // Prefix Length: 64 2324 // Flag: 0xc0, On-link flag(L), Autonomous address-configuration flag(A) 2325 // Valid Lifetime: Infinity (4294967295) 2326 // Preferred Lifetime: Infinity (4294967295) 2327 // Reserved 2328 // Prefix: 2401:fa00:480:f000:: 2329 // ICMPv6 Option (Recursive DNS Server 2401:fa00:480:f000::1) 2330 // Type: Recursive DNS Server (25) 2331 // Length: 3 (24 bytes) 2332 // Reserved 2333 // Lifetime: 7000 2334 // Recursive DNS Servers: 2401:fa00:480:f000::1 2335 // ICMPv6 Option (Advertisement Interval : 600000) 2336 // Type: Advertisement Interval (7) 2337 // Length: 1 (8 bytes) 2338 // Reserved 2339 // Advertisement Interval: 600000 2340 final String packetStringFmt = "33330000000128C68E23672C86DD60054C6B00603AFFFE800000000000002AC68EFFFE23672CFF02000000000000000000000000000186000ACD40C01B580000000000000000010128C68E23672C05010000000005DC030440C0%s000000002401FA000480F00000000000000000001903000000001B582401FA000480F000000000000000000107010000000927C0"; 2341 final List<String> lifetimes = List.of("FFFFFFFF", "00000000", "00000001", "00001B58"); 2342 for (String lifetime : lifetimes) { 2343 final byte[] ra = hexStringToByteArray( 2344 String.format(packetStringFmt, lifetime + lifetime)); 2345 // feed the RA into APF and generate the filter, the filter shouldn't crash. 2346 pretendPacketReceived(ra); 2347 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2348 } 2349 } 2350 2351 // Test for go/apf-ra-filter Case 1a. 2352 // Old lifetime is 0 2353 @Test testAcceptRaMinLftCase1a()2354 public void testAcceptRaMinLftCase1a() throws Exception { 2355 // configure accept_ra_min_lft 2356 final ApfConfiguration config = getDefaultConfig(); 2357 config.acceptRaMinLft = 180; 2358 final ApfFilter apfFilter = getApfFilter(config); 2359 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2360 2361 // Create an initial RA and build an APF program 2362 byte[] ra = new RaPacketBuilder(1800 /* router lifetime */) 2363 .addPioOption(1800 /*valid*/, 0 /*preferred*/, "2001:db8::/64") 2364 .build(); 2365 2366 pretendPacketReceived(ra); 2367 byte[] program = 2368 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2369 2370 // repeated RA is dropped 2371 assertDrop(program, ra); 2372 2373 // PIO preferred lifetime increases 2374 ra = new RaPacketBuilder(1800 /* router lifetime */) 2375 .addPioOption(1800 /*valid*/, 1 /*preferred*/, "2001:db8::/64") 2376 .build(); 2377 assertPass(program, ra); 2378 } 2379 2380 // Test for go/apf-ra-filter Case 2a. 2381 // Old lifetime is > 0 2382 @Test testAcceptRaMinLftCase2a()2383 public void testAcceptRaMinLftCase2a() throws Exception { 2384 // configure accept_ra_min_lft 2385 final ApfConfiguration config = getDefaultConfig(); 2386 config.acceptRaMinLft = 180; 2387 final ApfFilter apfFilter = getApfFilter(config); 2388 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2389 2390 // Create an initial RA and build an APF program 2391 byte[] ra = new RaPacketBuilder(1800 /* router lifetime */) 2392 .addPioOption(1800 /*valid*/, 100 /*preferred*/, "2001:db8::/64") 2393 .build(); 2394 2395 pretendPacketReceived(ra); 2396 byte[] program = 2397 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2398 2399 // repeated RA is dropped 2400 assertDrop(program, ra); 2401 2402 // PIO preferred lifetime increases 2403 ra = new RaPacketBuilder(1800 /* router lifetime */) 2404 .addPioOption(1800 /*valid*/, 101 /*preferred*/, "2001:db8::/64") 2405 .build(); 2406 assertPass(program, ra); 2407 2408 // PIO preferred lifetime decreases significantly 2409 ra = new RaPacketBuilder(1800 /* router lifetime */) 2410 .addPioOption(1800 /*valid*/, 33 /*preferred*/, "2001:db8::/64") 2411 .build(); 2412 assertPass(program, ra); 2413 } 2414 2415 2416 // Test for go/apf-ra-filter Case 1b. 2417 // Old lifetime is 0 2418 @Test testAcceptRaMinLftCase1b()2419 public void testAcceptRaMinLftCase1b() throws Exception { 2420 // configure accept_ra_min_lft 2421 final ApfConfiguration config = getDefaultConfig(); 2422 config.acceptRaMinLft = 180; 2423 final ApfFilter apfFilter = getApfFilter(config); 2424 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2425 2426 // Create an initial RA and build an APF program 2427 byte[] ra = new RaPacketBuilder(0 /* router lifetime */).build(); 2428 2429 pretendPacketReceived(ra); 2430 byte[] program = 2431 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2432 2433 // repeated RA is dropped 2434 assertDrop(program, ra); 2435 2436 // lifetime increases below accept_ra_min_lft 2437 ra = new RaPacketBuilder(179 /* router lifetime */).build(); 2438 assertDrop(program, ra); 2439 2440 // lifetime increases to accept_ra_min_lft 2441 ra = new RaPacketBuilder(180 /* router lifetime */).build(); 2442 assertPass(program, ra); 2443 } 2444 2445 // Test for go/apf-ra-filter Case 2b. 2446 // Old lifetime is < accept_ra_min_lft (but not 0). 2447 @Test testAcceptRaMinLftCase2b()2448 public void testAcceptRaMinLftCase2b() throws Exception { 2449 // configure accept_ra_min_lft 2450 final ApfConfiguration config = getDefaultConfig(); 2451 config.acceptRaMinLft = 180; 2452 final ApfFilter apfFilter = getApfFilter(config); 2453 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2454 2455 // Create an initial RA and build an APF program 2456 byte[] ra = new RaPacketBuilder(100 /* router lifetime */).build(); 2457 2458 pretendPacketReceived(ra); 2459 byte[] program = 2460 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2461 2462 // repeated RA is dropped 2463 assertDrop(program, ra); 2464 2465 // lifetime increases 2466 ra = new RaPacketBuilder(101 /* router lifetime */).build(); 2467 assertDrop(program, ra); 2468 2469 // lifetime decreases significantly 2470 ra = new RaPacketBuilder(1 /* router lifetime */).build(); 2471 assertDrop(program, ra); 2472 2473 // equals accept_ra_min_lft 2474 ra = new RaPacketBuilder(180 /* router lifetime */).build(); 2475 assertPass(program, ra); 2476 2477 // lifetime is 0 2478 ra = new RaPacketBuilder(0 /* router lifetime */).build(); 2479 assertPass(program, ra); 2480 } 2481 2482 // Test for go/apf-ra-filter Case 3b. 2483 // Old lifetime is >= accept_ra_min_lft and <= 3 * accept_ra_min_lft 2484 @Test testAcceptRaMinLftCase3b()2485 public void testAcceptRaMinLftCase3b() throws Exception { 2486 // configure accept_ra_min_lft 2487 final ApfConfiguration config = getDefaultConfig(); 2488 config.acceptRaMinLft = 180; 2489 final ApfFilter apfFilter = getApfFilter(config); 2490 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2491 2492 // Create an initial RA and build an APF program 2493 byte[] ra = new RaPacketBuilder(200 /* router lifetime */).build(); 2494 2495 pretendPacketReceived(ra); 2496 byte[] program = 2497 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2498 2499 // repeated RA is dropped 2500 assertDrop(program, ra); 2501 2502 // lifetime increases 2503 ra = new RaPacketBuilder(201 /* router lifetime */).build(); 2504 assertPass(program, ra); 2505 2506 // lifetime is below accept_ra_min_lft (but not 0) 2507 ra = new RaPacketBuilder(1 /* router lifetime */).build(); 2508 assertDrop(program, ra); 2509 2510 // lifetime is 0 2511 ra = new RaPacketBuilder(0 /* router lifetime */).build(); 2512 assertPass(program, ra); 2513 } 2514 2515 // Test for go/apf-ra-filter Case 4b. 2516 // Old lifetime is > 3 * accept_ra_min_lft 2517 @Test testAcceptRaMinLftCase4b()2518 public void testAcceptRaMinLftCase4b() throws Exception { 2519 // configure accept_ra_min_lft 2520 final ApfConfiguration config = getDefaultConfig(); 2521 config.acceptRaMinLft = 180; 2522 final ApfFilter apfFilter = getApfFilter(config); 2523 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2524 2525 // Create an initial RA and build an APF program 2526 byte[] ra = new RaPacketBuilder(1800 /* router lifetime */).build(); 2527 2528 pretendPacketReceived(ra); 2529 byte[] program = 2530 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2531 2532 // repeated RA is dropped 2533 assertDrop(program, ra); 2534 2535 // lifetime increases 2536 ra = new RaPacketBuilder(1801 /* router lifetime */).build(); 2537 assertPass(program, ra); 2538 2539 // lifetime is 1/3 of old lft 2540 ra = new RaPacketBuilder(600 /* router lifetime */).build(); 2541 assertDrop(program, ra); 2542 2543 // lifetime is below 1/3 of old lft 2544 ra = new RaPacketBuilder(599 /* router lifetime */).build(); 2545 assertPass(program, ra); 2546 2547 // lifetime is below accept_ra_min_lft (but not 0) 2548 ra = new RaPacketBuilder(1 /* router lifetime */).build(); 2549 assertDrop(program, ra); 2550 2551 // lifetime is 0 2552 ra = new RaPacketBuilder(0 /* router lifetime */).build(); 2553 assertPass(program, ra); 2554 } 2555 2556 @Test testRaFilterIsUpdated()2557 public void testRaFilterIsUpdated() throws Exception { 2558 // configure accept_ra_min_lft 2559 final ApfConfiguration config = getDefaultConfig(); 2560 config.acceptRaMinLft = 180; 2561 final ApfFilter apfFilter = getApfFilter(config); 2562 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2563 2564 // Create an initial RA and build an APF program 2565 byte[] ra = new RaPacketBuilder(1800 /* router lifetime */).build(); 2566 pretendPacketReceived(ra); 2567 byte[] program = 2568 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2569 2570 // repeated RA is dropped. 2571 assertDrop(program, ra); 2572 2573 // updated RA is passed, repeated RA is dropped after program update. 2574 ra = new RaPacketBuilder(599 /* router lifetime */).build(); 2575 assertPass(program, ra); 2576 pretendPacketReceived(ra); 2577 program = mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2578 assertDrop(program, ra); 2579 2580 ra = new RaPacketBuilder(180 /* router lifetime */).build(); 2581 assertPass(program, ra); 2582 pretendPacketReceived(ra); 2583 program = mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2584 assertDrop(program, ra); 2585 2586 ra = new RaPacketBuilder(0 /* router lifetime */).build(); 2587 assertPass(program, ra); 2588 pretendPacketReceived(ra); 2589 program = mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2590 assertDrop(program, ra); 2591 2592 ra = new RaPacketBuilder(180 /* router lifetime */).build(); 2593 assertPass(program, ra); 2594 pretendPacketReceived(ra); 2595 program = mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2596 assertDrop(program, ra); 2597 2598 ra = new RaPacketBuilder(599 /* router lifetime */).build(); 2599 assertPass(program, ra); 2600 pretendPacketReceived(ra); 2601 program = mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2602 assertDrop(program, ra); 2603 2604 ra = new RaPacketBuilder(1800 /* router lifetime */).build(); 2605 assertPass(program, ra); 2606 pretendPacketReceived(ra); 2607 program = mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2608 assertDrop(program, ra); 2609 } 2610 2611 @Test testBroadcastAddress()2612 public void testBroadcastAddress() throws Exception { 2613 assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 0)); 2614 assertEqualsIp("0.0.0.0", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 32)); 2615 assertEqualsIp("0.0.3.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 22)); 2616 assertEqualsIp("0.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 8)); 2617 2618 assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 0)); 2619 assertEqualsIp("10.0.0.1", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 32)); 2620 assertEqualsIp("10.0.0.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 24)); 2621 assertEqualsIp("10.0.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 16)); 2622 } 2623 assertEqualsIp(String expected, int got)2624 public void assertEqualsIp(String expected, int got) throws Exception { 2625 int want = Inet4AddressUtils.inet4AddressToIntHTH( 2626 (Inet4Address) InetAddresses.parseNumericAddress(expected)); 2627 assertEquals(want, got); 2628 } 2629 2630 @Test testInstallPacketFilterFailure()2631 public void testInstallPacketFilterFailure() throws Exception { 2632 doReturn(false).when(mApfController).installPacketFilter(any(), any()); 2633 final ApfConfiguration config = getDefaultConfig(); 2634 final ApfFilter apfFilter = getApfFilter(config); 2635 2636 verify(mNetworkQuirkMetrics).setEvent(NetworkQuirkEvent.QE_APF_INSTALL_FAILURE); 2637 verify(mNetworkQuirkMetrics).statsWrite(); 2638 reset(mNetworkQuirkMetrics); 2639 synchronized (apfFilter) { 2640 apfFilter.installNewProgram(); 2641 } 2642 verify(mNetworkQuirkMetrics).setEvent(NetworkQuirkEvent.QE_APF_INSTALL_FAILURE); 2643 verify(mNetworkQuirkMetrics).statsWrite(); 2644 } 2645 2646 2647 @Test testApfProgramOverSize()2648 public void testApfProgramOverSize() throws Exception { 2649 final ApfConfiguration config = getDefaultConfig(); 2650 config.apfVersionSupported = 2; 2651 config.apfRamSize = 256; 2652 final ApfFilter apfFilter = getApfFilter(config); 2653 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2654 verify(mNetworkQuirkMetrics).setEvent(NetworkQuirkEvent.QE_APF_OVER_SIZE_FAILURE); 2655 verify(mNetworkQuirkMetrics).statsWrite(); 2656 } 2657 2658 @Test testApfSessionInfoMetrics()2659 public void testApfSessionInfoMetrics() throws Exception { 2660 final ApfConfiguration config = getDefaultConfig(); 2661 config.apfVersionSupported = 4; 2662 config.apfRamSize = 4096; 2663 final long startTimeMs = 12345; 2664 final long durationTimeMs = config.minMetricsSessionDurationMs; 2665 doReturn(startTimeMs).when(mDependencies).elapsedRealtime(); 2666 final ApfFilter apfFilter = getApfFilter(config); 2667 byte[] program = 2668 mApfTestHelpers.consumeInstalledProgram(mApfController, 2 /* installCnt */); 2669 int maxProgramSize = 0; 2670 int numProgramUpdated = 0; 2671 maxProgramSize = Math.max(maxProgramSize, program.length); 2672 numProgramUpdated++; 2673 2674 final byte[] data = new byte[Counter.totalSize()]; 2675 final byte[] expectedData = data.clone(); 2676 final int totalPacketsCounterIdx = Counter.totalSize() + Counter.TOTAL_PACKETS.offset(); 2677 final int passedIpv6IcmpCounterIdx = 2678 Counter.totalSize() + Counter.PASSED_IPV6_ICMP.offset(); 2679 final int droppedIpv4MulticastIdx = 2680 Counter.totalSize() + Counter.DROPPED_IPV4_MULTICAST.offset(); 2681 2682 // Receive an RA packet (passed). 2683 final byte[] ra = buildLargeRa(); 2684 expectedData[totalPacketsCounterIdx + 3] += 1; 2685 expectedData[passedIpv6IcmpCounterIdx + 3] += 1; 2686 assertDataMemoryContentsIgnoreVersion(PASS, program, ra, data, expectedData); 2687 pretendPacketReceived(ra); 2688 program = mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2689 maxProgramSize = Math.max(maxProgramSize, program.length); 2690 numProgramUpdated++; 2691 2692 apfFilter.setMulticastFilter(true); 2693 // setMulticastFilter will trigger program installation. 2694 program = mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2695 maxProgramSize = Math.max(maxProgramSize, program.length); 2696 numProgramUpdated++; 2697 2698 // Receive IPv4 multicast packet (dropped). 2699 final byte[] multicastIpv4Addr = {(byte) 224, 0, 0, 1}; 2700 ByteBuffer mcastv4packet = makeIpv4Packet(IPPROTO_UDP); 2701 put(mcastv4packet, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr); 2702 expectedData[totalPacketsCounterIdx + 3] += 1; 2703 expectedData[droppedIpv4MulticastIdx + 3] += 1; 2704 assertDataMemoryContentsIgnoreVersion(DROP, program, mcastv4packet.array(), data, 2705 expectedData); 2706 2707 // Set data snapshot and update counters. 2708 apfFilter.setDataSnapshot(data); 2709 2710 // Write metrics data to statsd pipeline when shutdown. 2711 doReturn(startTimeMs + durationTimeMs).when(mDependencies).elapsedRealtime(); 2712 mHandler.post(apfFilter::shutdown); 2713 IoUtils.closeQuietly(mWriteSocket); 2714 HandlerUtils.waitForIdle(mHandler, TIMEOUT_MS); 2715 verify(mApfSessionInfoMetrics).setVersion(4); 2716 verify(mApfSessionInfoMetrics).setMemorySize(4096); 2717 2718 // Verify Counters 2719 final Map<Counter, Long> expectedCounters = Map.of(Counter.TOTAL_PACKETS, 2L, 2720 Counter.PASSED_IPV6_ICMP, 1L, Counter.DROPPED_IPV4_MULTICAST, 1L); 2721 final ArgumentCaptor<Counter> counterCaptor = ArgumentCaptor.forClass(Counter.class); 2722 final ArgumentCaptor<Long> valueCaptor = ArgumentCaptor.forClass(Long.class); 2723 verify(mApfSessionInfoMetrics, times(expectedCounters.size())).addApfCounter( 2724 counterCaptor.capture(), valueCaptor.capture()); 2725 final List<Counter> counters = counterCaptor.getAllValues(); 2726 final List<Long> values = valueCaptor.getAllValues(); 2727 final ArrayMap<Counter, Long> capturedCounters = new ArrayMap<>(); 2728 for (int i = 0; i < counters.size(); i++) { 2729 capturedCounters.put(counters.get(i), values.get(i)); 2730 } 2731 assertEquals(expectedCounters, capturedCounters); 2732 2733 verify(mApfSessionInfoMetrics).setApfSessionDurationSeconds( 2734 (int) (durationTimeMs / DateUtils.SECOND_IN_MILLIS)); 2735 verify(mApfSessionInfoMetrics).setNumOfTimesApfProgramUpdated(numProgramUpdated); 2736 verify(mApfSessionInfoMetrics).setMaxProgramSize(maxProgramSize); 2737 verify(mApfSessionInfoMetrics).statsWrite(); 2738 } 2739 2740 @Test testIpClientRaInfoMetrics()2741 public void testIpClientRaInfoMetrics() throws Exception { 2742 final ApfConfiguration config = getDefaultConfig(); 2743 final long startTimeMs = 12345; 2744 final long durationTimeMs = config.minMetricsSessionDurationMs; 2745 doReturn(startTimeMs).when(mDependencies).elapsedRealtime(); 2746 final ApfFilter apfFilter = getApfFilter(config); 2747 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2748 2749 final int routerLifetime = 1000; 2750 final int prefixValidLifetime = 200; 2751 final int prefixPreferredLifetime = 100; 2752 final int rdnssLifetime = 300; 2753 final int routeLifetime = 400; 2754 2755 // Construct 2 RAs with partial lifetimes larger than predefined constants 2756 final RaPacketBuilder ra1 = new RaPacketBuilder(routerLifetime); 2757 ra1.addPioOption(prefixValidLifetime + 123, prefixPreferredLifetime, "2001:db8::/64"); 2758 ra1.addRdnssOption(rdnssLifetime, "2001:4860:4860::8888", "2001:4860:4860::8844"); 2759 ra1.addRioOption(routeLifetime + 456, "64:ff9b::/96"); 2760 final RaPacketBuilder ra2 = new RaPacketBuilder(routerLifetime + 123); 2761 ra2.addPioOption(prefixValidLifetime, prefixPreferredLifetime, "2001:db9::/64"); 2762 ra2.addRdnssOption(rdnssLifetime + 456, "2001:4860:4860::8888", "2001:4860:4860::8844"); 2763 ra2.addRioOption(routeLifetime, "64:ff9b::/96"); 2764 2765 // Construct an invalid RA packet 2766 final RaPacketBuilder raInvalid = new RaPacketBuilder(routerLifetime); 2767 raInvalid.addZeroLengthOption(); 2768 2769 // Construct 4 different kinds of zero lifetime RAs 2770 final RaPacketBuilder raZeroRouterLifetime = new RaPacketBuilder(0 /* routerLft */); 2771 final RaPacketBuilder raZeroPioValidLifetime = new RaPacketBuilder(routerLifetime); 2772 raZeroPioValidLifetime.addPioOption(0, prefixPreferredLifetime, "2001:db10::/64"); 2773 final RaPacketBuilder raZeroRdnssLifetime = new RaPacketBuilder(routerLifetime); 2774 raZeroRdnssLifetime.addPioOption( 2775 prefixValidLifetime, prefixPreferredLifetime, "2001:db11::/64"); 2776 raZeroRdnssLifetime.addRdnssOption(0, "2001:4860:4860::8888", "2001:4860:4860::8844"); 2777 final RaPacketBuilder raZeroRioRouteLifetime = new RaPacketBuilder(routerLifetime); 2778 raZeroRioRouteLifetime.addPioOption( 2779 prefixValidLifetime, prefixPreferredLifetime, "2001:db12::/64"); 2780 raZeroRioRouteLifetime.addRioOption(0, "64:ff9b::/96"); 2781 2782 // Inject RA packets. Calling assertProgramUpdateAndGet()/assertNoProgramUpdate() is to make 2783 // sure that the RA packet has been processed. 2784 pretendPacketReceived(ra1.build()); 2785 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2786 pretendPacketReceived(ra2.build()); 2787 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2788 pretendPacketReceived(raInvalid.build()); 2789 Thread.sleep(NO_CALLBACK_TIMEOUT_MS); 2790 verify(mApfController, never()).installPacketFilter(any(), any()); 2791 pretendPacketReceived(raZeroRouterLifetime.build()); 2792 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2793 pretendPacketReceived(raZeroPioValidLifetime.build()); 2794 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2795 pretendPacketReceived(raZeroRdnssLifetime.build()); 2796 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2797 pretendPacketReceived(raZeroRioRouteLifetime.build()); 2798 mApfTestHelpers.consumeInstalledProgram(mApfController, 1 /* installCnt */); 2799 2800 // Write metrics data to statsd pipeline when shutdown. 2801 doReturn(startTimeMs + durationTimeMs).when(mDependencies).elapsedRealtime(); 2802 mHandler.post(apfFilter::shutdown); 2803 IoUtils.closeQuietly(mWriteSocket); 2804 HandlerUtils.waitForIdle(mHandler, TIMEOUT_MS); 2805 2806 // Verify each metric fields in IpClientRaInfoMetrics. 2807 verify(mIpClientRaInfoMetrics).setMaxNumberOfDistinctRas(6); 2808 verify(mIpClientRaInfoMetrics).setNumberOfZeroLifetimeRas(4); 2809 verify(mIpClientRaInfoMetrics).setNumberOfParsingErrorRas(1); 2810 verify(mIpClientRaInfoMetrics).setLowestRouterLifetimeSeconds(routerLifetime); 2811 verify(mIpClientRaInfoMetrics).setLowestPioValidLifetimeSeconds(prefixValidLifetime); 2812 verify(mIpClientRaInfoMetrics).setLowestRioRouteLifetimeSeconds(routeLifetime); 2813 verify(mIpClientRaInfoMetrics).setLowestRdnssLifetimeSeconds(rdnssLifetime); 2814 verify(mIpClientRaInfoMetrics).statsWrite(); 2815 } 2816 2817 @Test testNoMetricsWrittenForShortDuration()2818 public void testNoMetricsWrittenForShortDuration() throws Exception { 2819 final ApfConfiguration config = getDefaultConfig(); 2820 final long startTimeMs = 12345; 2821 final long durationTimeMs = config.minMetricsSessionDurationMs; 2822 2823 // Verify no metrics data written to statsd for duration less than durationTimeMs. 2824 doReturn(startTimeMs).when(mDependencies).elapsedRealtime(); 2825 final ApfFilter apfFilter = getApfFilter(config); 2826 doReturn(startTimeMs + durationTimeMs - 1).when(mDependencies).elapsedRealtime(); 2827 mHandler.post(apfFilter::shutdown); 2828 HandlerUtils.waitForIdle(mHandler, TIMEOUT_MS); 2829 verify(mApfSessionInfoMetrics, never()).statsWrite(); 2830 verify(mIpClientRaInfoMetrics, never()).statsWrite(); 2831 2832 // Verify metrics data written to statsd for duration greater than or equal to 2833 // durationTimeMs. 2834 doReturn(startTimeMs).when(mDependencies).elapsedRealtime(); 2835 final ApfFilter apfFilter2 = getApfFilter(config); 2836 doReturn(startTimeMs + durationTimeMs).when(mDependencies).elapsedRealtime(); 2837 mHandler.post(apfFilter2::shutdown); 2838 HandlerUtils.waitForIdle(mHandler, TIMEOUT_MS); 2839 verify(mApfSessionInfoMetrics).statsWrite(); 2840 verify(mIpClientRaInfoMetrics).statsWrite(); 2841 } 2842 deriveApfGeneratorVersion(ApfV4GeneratorBase<?> gen)2843 private int deriveApfGeneratorVersion(ApfV4GeneratorBase<?> gen) { 2844 if (gen instanceof ApfV4Generator) { 2845 return 4; 2846 } else if (gen instanceof ApfV6Generator) { 2847 return 6; 2848 } 2849 return -1; 2850 } 2851 2852 @Test testApfGeneratorPropagation()2853 public void testApfGeneratorPropagation() throws IllegalInstructionException { 2854 ApfV4Generator v4Gen = new ApfV4Generator(APF_VERSION_3, 1024 /* ramSize */, 2855 1024 /* clampSize */); 2856 ApfV6Generator v6Gen = new ApfV6Generator(APF_VERSION_6, 1024 /* ramSize */, 2857 1024 /* clampSize */); 2858 assertEquals(4, deriveApfGeneratorVersion(v4Gen)); 2859 assertEquals(6, deriveApfGeneratorVersion(v6Gen)); 2860 } 2861 2862 @Test testFullApfV4ProgramGenerationIPV6()2863 public void testFullApfV4ProgramGenerationIPV6() throws IllegalInstructionException { 2864 ApfV4Generator gen = new ApfV4Generator(APF_VERSION_3, 1024 /* ramSize */, 2865 1024 /* clampSize */); 2866 gen.addLoadImmediate(R1, -4); 2867 gen.addLoadData(R0, 0); 2868 gen.addAdd(1); 2869 gen.addStoreData(R0, 0); 2870 gen.addLoad16intoR0(12); 2871 gen.addLoadImmediate(R1, -108); 2872 gen.addJumpIfR0LessThan(0x600, (short) -504); 2873 gen.addLoadImmediate(R1, -112); 2874 gen.addJumpIfR0Equals(0x88a2, (short) -504); 2875 gen.addJumpIfR0Equals(0x88a4, (short) -504); 2876 gen.addJumpIfR0Equals(0x88b8, (short) -504); 2877 gen.addJumpIfR0Equals(0x88cd, (short) -504); 2878 gen.addJumpIfR0Equals(0x88e1, (short) -504); 2879 gen.addJumpIfR0Equals(0x88e3, (short) -504); 2880 gen.addJumpIfR0NotEquals(0x806, (short) -116); 2881 gen.addLoadImmediate(R0, 14); 2882 gen.addLoadImmediate(R1, -36); 2883 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("000108000604"), (short) -498); 2884 gen.addLoad16intoR0(20); 2885 gen.addJumpIfR0Equals(0x1, (short) -102); 2886 gen.addLoadImmediate(R1, -40); 2887 gen.addJumpIfR0NotEquals(0x2, (short) -498); 2888 gen.addLoad32intoR0(28); 2889 gen.addLoadImmediate(R1, -116); 2890 gen.addJumpIfR0Equals(0x0, (short) -504); 2891 gen.addLoadImmediate(R0, 0); 2892 gen.addLoadImmediate(R1, -44); 2893 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("ffffffffffff"), (short) -498); 2894 2895 gen.defineLabel((short) -102); 2896 gen.addLoad32intoR0(38); 2897 gen.addLoadImmediate(R1, -64); 2898 gen.addJumpIfR0Equals(0x0, (short) -504); 2899 gen.addLoadImmediate(R1, -8); 2900 gen.addJump((short) -498); 2901 2902 gen.defineLabel((short) -116); 2903 gen.addLoad16intoR0(12); 2904 gen.addJumpIfR0NotEquals(0x800, (short) -207); 2905 gen.addLoad8intoR0(23); 2906 gen.addJumpIfR0NotEquals(0x11, (short) -159); 2907 gen.addLoad16intoR0(20); 2908 gen.addJumpIfR0AnyBitsSet(0x1fff, (short) -159); 2909 gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE); 2910 gen.addLoad16R1IndexedIntoR0(16); 2911 gen.addJumpIfR0NotEquals(0x44, (short) -159); 2912 gen.addLoadImmediate(R0, 50); 2913 gen.addAddR1ToR0(); 2914 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("e212507c6345"), (short) -159); 2915 gen.addLoadImmediate(R1, -12); 2916 gen.addJump((short) -498); 2917 2918 gen.defineLabel((short) -159); 2919 gen.addLoad8intoR0(30); 2920 gen.addAnd(240); 2921 gen.addLoadImmediate(R1, -84); 2922 gen.addJumpIfR0Equals(0xe0, (short) -504); 2923 gen.addLoadImmediate(R1, -76); 2924 gen.addLoad32intoR0(30); 2925 gen.addJumpIfR0Equals(0xffffffff, (short) -504); 2926 gen.addLoadImmediate(R1, -24); 2927 gen.addLoadImmediate(R0, 0); 2928 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("ffffffffffff"), (short) -498); 2929 gen.addLoadImmediate(R1, -72); 2930 gen.addJump((short) -504); 2931 gen.addLoadImmediate(R1, -16); 2932 gen.addJump((short) -498); 2933 2934 gen.defineLabel((short) -207); 2935 gen.addJumpIfR0Equals(0x86dd, (short) -231); 2936 gen.addLoadImmediate(R0, 0); 2937 gen.addLoadImmediate(R1, -48); 2938 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("ffffffffffff"), (short) -498); 2939 gen.addLoadImmediate(R1, -56); 2940 gen.addJump((short) -504); 2941 2942 gen.defineLabel((short) -231); 2943 gen.addLoad8intoR0(20); 2944 gen.addJumpIfR0Equals(0x3a, (short) -249); 2945 gen.addLoadImmediate(R1, -104); 2946 gen.addLoad8intoR0(38); 2947 gen.addJumpIfR0Equals(0xff, (short) -504); 2948 gen.addLoadImmediate(R1, -32); 2949 gen.addJump((short) -498); 2950 2951 gen.defineLabel((short) -249); 2952 gen.addLoad8intoR0(54); 2953 gen.addLoadImmediate(R1, -88); 2954 gen.addJumpIfR0Equals(0x85, (short) -504); 2955 gen.addJumpIfR0NotEquals(0x88, (short) -283); 2956 gen.addLoadImmediate(R0, 38); 2957 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("ff0200000000000000000000000000"), (short) -283); 2958 gen.addLoadImmediate(R1, -92); 2959 gen.addJump((short) -504); 2960 2961 gen.defineLabel((short) -283); 2962 gen.addLoadFromMemory(R0, MemorySlot.PACKET_SIZE); 2963 gen.addJumpIfR0NotEquals(0xa6, (short) -496); 2964 gen.addLoadFromMemory(R0, MemorySlot.FILTER_AGE_SECONDS); 2965 gen.addJumpIfR0GreaterThan(0x254, (short) -496); 2966 gen.addLoadImmediate(R0, 0); 2967 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("e212507c6345648788fd6df086dd68"), (short) -496); 2968 gen.addLoadImmediate(R0, 18); 2969 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("00703afffe800000000000002a0079e10abc1539fe80000000000000e01250fffe7c63458600"), (short) -496); 2970 gen.addLoadImmediate(R0, 58); 2971 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("4000"), (short) -496); 2972 gen.addLoad16intoR0(60); 2973 gen.addJumpIfR0LessThan(0x254, (short) -496); 2974 gen.addLoadImmediate(R0, 62); 2975 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("0000000000000000"), (short) -496); 2976 gen.addLoadImmediate(R0, 78); 2977 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("19050000"), (short) -496); 2978 gen.addLoad32intoR0(82); 2979 gen.addJumpIfR0LessThan(0x254, (short) -496); 2980 gen.addLoadImmediate(R0, 86); 2981 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("2001486048600000000000000000646420014860486000000000000000000064"), (short) -496); 2982 gen.addLoadImmediate(R0, 118); 2983 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("030440c0"), (short) -496); 2984 gen.addLoad32intoR0(122); 2985 gen.addJumpIfR0LessThan(0x254, (short) -496); 2986 gen.addLoad32intoR0(126); 2987 gen.addJumpIfR0LessThan(0x254, (short) -496); 2988 gen.addLoadImmediate(R0, 130); 2989 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("00000000"), (short) -496); 2990 gen.addLoadImmediate(R0, 134); 2991 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("2a0079e10abc15390000000000000000"), (short) -496); 2992 gen.addLoadImmediate(R1, -60); 2993 gen.addJump((short) -504); 2994 2995 gen.defineLabel((short) -496); 2996 gen.addLoadImmediate(R1, -28); 2997 2998 gen.defineLabel((short) -498); 2999 gen.addLoadData(R0, 0); 3000 gen.addAdd(1); 3001 gen.addStoreData(R0, 0); 3002 gen.addJump(PASS_LABEL); 3003 3004 gen.defineLabel((short) -504); 3005 gen.addLoadData(R0, 0); 3006 gen.addAdd(1); 3007 gen.addStoreData(R0, 0); 3008 gen.addJump(DROP_LABEL); 3009 3010 byte[] program = gen.generate(); 3011 final String programString = toHexString(program).toLowerCase(); 3012 final String referenceProgramHexString = "6bfcb03a01b8120c6b949401e906006b907c01e288a27c01dd88a47c01d888b87c01d388cd7c01ce88e17c01c988e384004008066a0e6bdca401af000600010800060412147a1e016bd88401a300021a1c6b8c7c01a00000686bd4a4018c0006ffffffffffff1a266bc07c018900006bf874017e120c84005408000a17821f1112149c00181fffab0d2a108211446a3239a20506e212507c63456bf47401530a1e52f06bac7c014e00e06bb41a1e7e00000141ffffffff6be868a4012d0006ffffffffffff6bb874012e6bf07401237c001386dd686bd0a401100006ffffffffffff6bc87401110a147a0d3a6b980a267c010300ff6be072f90a366ba87af8858218886a26a2040fff02000000000000000000000000006ba472ddaa0e82d0a6aa0f8c00c9025468a2b60fe212507c6345648788fd6df086dd686a12a28b2600703afffe800000000000002a0079e10abc1539fe80000000000000e01250fffe7c634586006a3aa284024000123c94007d02546a3ea2700800000000000000006a4ea26704190500001a5294006002546a56a23b2020014860486000000000000000006464200148604860000000000000000000646a76a23204030440c01a7a94002b02541a7e94002402546c0082a21a04000000006c0086a204102a0079e10abc153900000000000000006bc472086be4b03a01b87206b03a01b87201"; 3013 assertEquals(referenceProgramHexString, programString); 3014 } 3015 3016 @Test testFullApfV4ProgramGenerationIPV4()3017 public void testFullApfV4ProgramGenerationIPV4() throws IllegalInstructionException { 3018 ApfV4Generator gen = new ApfV4Generator(APF_VERSION_3, 1024 /* ramSize */, 3019 1024 /* clampSize */); 3020 gen.addLoadImmediate(R1, -4); 3021 gen.addLoadData(R0, 0); 3022 gen.addAdd(1); 3023 gen.addStoreData(R0, 0); 3024 gen.addLoad16intoR0(12); 3025 gen.addLoadImmediate(R1, -108); 3026 gen.addJumpIfR0LessThan(0x600, (short) -283); 3027 gen.addLoadImmediate(R1, -112); 3028 gen.addJumpIfR0Equals(0x88a2, (short) -283); 3029 gen.addJumpIfR0Equals(0x88a4, (short) -283); 3030 gen.addJumpIfR0Equals(0x88b8, (short) -283); 3031 gen.addJumpIfR0Equals(0x88cd, (short) -283); 3032 gen.addJumpIfR0Equals(0x88e1, (short) -283); 3033 gen.addJumpIfR0Equals(0x88e3, (short) -283); 3034 gen.addJumpIfR0NotEquals(0x806, (short) -109); 3035 gen.addLoadImmediate(R0, 14); 3036 gen.addLoadImmediate(R1, -36); 3037 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("000108000604"), (short) -277); 3038 gen.addLoad16intoR0(20); 3039 gen.addJumpIfR0Equals(0x1, (short) -94); 3040 gen.addLoadImmediate(R1, -40); 3041 gen.addJumpIfR0NotEquals(0x2, (short) -277); 3042 gen.addLoad32intoR0(28); 3043 gen.addLoadImmediate(R1, -116); 3044 gen.addJumpIfR0Equals(0x0, (short) -283); 3045 gen.addLoadImmediate(R0, 0); 3046 gen.addLoadImmediate(R1, -44); 3047 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("ffffffffffff"), (short) -277); 3048 3049 gen.defineLabel((short) -94); 3050 gen.addLoadImmediate(R0, 38); 3051 gen.addLoadImmediate(R1, -68); 3052 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("c0a801b3"), (short) -283); 3053 gen.addLoadImmediate(R1, -8); 3054 gen.addJump((short) -277); 3055 3056 gen.defineLabel((short) -109); 3057 gen.addLoad16intoR0(12); 3058 gen.addJumpIfR0NotEquals(0x800, (short) -204); 3059 gen.addLoad8intoR0(23); 3060 gen.addJumpIfR0NotEquals(0x11, (short) -151); 3061 gen.addLoad16intoR0(20); 3062 gen.addJumpIfR0AnyBitsSet(0x1fff, (short) -151); 3063 gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE); 3064 gen.addLoad16R1IndexedIntoR0(16); 3065 gen.addJumpIfR0NotEquals(0x44, (short) -151); 3066 gen.addLoadImmediate(R0, 50); 3067 gen.addAddR1ToR0(); 3068 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("f683d58f832b"), (short) -151); 3069 gen.addLoadImmediate(R1, -12); 3070 gen.addJump((short) -277); 3071 3072 gen.defineLabel((short) -151); 3073 gen.addLoad8intoR0(30); 3074 gen.addAnd(240); 3075 gen.addLoadImmediate(R1, -84); 3076 gen.addJumpIfR0Equals(0xe0, (short) -283); 3077 gen.addLoadImmediate(R1, -76); 3078 gen.addLoad32intoR0(30); 3079 gen.addJumpIfR0Equals(0xffffffff, (short) -283); 3080 gen.addLoadImmediate(R1, -80); 3081 gen.addJumpIfR0Equals(0xc0a801ff, (short) -283); 3082 gen.addLoadImmediate(R1, -24); 3083 gen.addLoadImmediate(R0, 0); 3084 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("ffffffffffff"), (short) -277); 3085 gen.addLoadImmediate(R1, -72); 3086 gen.addJump((short) -283); 3087 gen.addLoadImmediate(R1, -16); 3088 gen.addJump((short) -277); 3089 3090 gen.defineLabel((short) -204); 3091 gen.addJumpIfR0Equals(0x86dd, (short) -225); 3092 gen.addLoadImmediate(R0, 0); 3093 gen.addLoadImmediate(R1, -48); 3094 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("ffffffffffff"), (short) -277); 3095 gen.addLoadImmediate(R1, -56); 3096 gen.addJump((short) -283); 3097 3098 gen.defineLabel((short) -225); 3099 gen.addLoad8intoR0(20); 3100 gen.addJumpIfR0Equals(0x3a, (short) -241); 3101 gen.addLoadImmediate(R1, -104); 3102 gen.addLoad8intoR0(38); 3103 gen.addJumpIfR0Equals(0xff, (short) -283); 3104 gen.addLoadImmediate(R1, -32); 3105 gen.addJump((short) -277); 3106 3107 gen.defineLabel((short) -241); 3108 gen.addLoad8intoR0(54); 3109 gen.addLoadImmediate(R1, -88); 3110 gen.addJumpIfR0Equals(0x85, (short) -283); 3111 gen.addJumpIfR0NotEquals(0x88, (short) -275); 3112 gen.addLoadImmediate(R0, 38); 3113 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("ff0200000000000000000000000000"), (short) -275); 3114 gen.addLoadImmediate(R1, -92); 3115 gen.addJump((short) -283); 3116 3117 gen.defineLabel((short) -275); 3118 gen.addLoadImmediate(R1, -28); 3119 3120 gen.defineLabel((short) -277); 3121 gen.addLoadData(R0, 0); 3122 gen.addAdd(1); 3123 gen.addStoreData(R0, 0); 3124 gen.addJump(PASS_LABEL); 3125 3126 gen.defineLabel((short) -283); 3127 gen.addLoadData(R0, 0); 3128 gen.addAdd(1); 3129 gen.addStoreData(R0, 0); 3130 gen.addJump(DROP_LABEL); 3131 3132 byte[] program = gen.generate(); 3133 final String programString = toHexString(program).toLowerCase(); 3134 final String referenceProgramHexString = "6bfcb03a01b8120c6b9494010c06006b907c010588a27c010088a47c00fb88b87c00f688cd7c00f188e17c00ec88e384003908066a0e6bdca2d40600010800060412147a18016bd882ca021a1c6b8c7ac900686bd4a2b706ffffffffffff6a266bbca2b204c0a801b36bf872a8120c84005808000a17821e1112149c00171fffab0d2a108210446a3239a20406f683d58f832b6bf4727e0a1e52f06bac7a7be06bb41a1e7e0000006effffffff6bb07e00000063c0a801ff6be868a25106ffffffffffff6bb872536bf072497c001086dd686bd0a23806ffffffffffff6bc8723a0a147a0b3a6b980a267a2eff6be072240a366ba87a23858218886a26a2040fff02000000000000000000000000006ba472086be4b03a01b87206b03a01b87201"; 3135 assertEquals(referenceProgramHexString, programString); 3136 } 3137 3138 @Test testFullApfV4ProgramGenerationNatTKeepAliveV4()3139 public void testFullApfV4ProgramGenerationNatTKeepAliveV4() throws IllegalInstructionException { 3140 ApfV4Generator gen = new ApfV4Generator(APF_VERSION_3, mRamSize, mClampSize, true); 3141 gen.addLoadImmediate(R1, -4); 3142 gen.addLoadData(R0, 0); 3143 gen.addAdd(1); 3144 gen.addStoreData(R0, 0); 3145 gen.addLoad16intoR0(12); 3146 gen.addCountAndDropIfR0LessThan(0x600, getCounterEnumFromOffset(-108)); 3147 gen.addLoadImmediate(R1, -112); 3148 gen.addJumpIfR0Equals(0x88a2, gen.mCountAndDropLabel); 3149 gen.addJumpIfR0Equals(0x88a4, gen.mCountAndDropLabel); 3150 gen.addJumpIfR0Equals(0x88b8, gen.mCountAndDropLabel); 3151 gen.addJumpIfR0Equals(0x88cd, gen.mCountAndDropLabel); 3152 gen.addJumpIfR0Equals(0x88e1, gen.mCountAndDropLabel); 3153 gen.addJumpIfR0Equals(0x88e3, gen.mCountAndDropLabel); 3154 gen.addJumpIfR0NotEquals(0x806, (short) -115); 3155 gen.addLoadImmediate(R0, 14); 3156 gen.addCountAndPassIfBytesAtR0NotEqual(hexStringToByteArray("000108000604"), getCounterEnumFromOffset(-36)); 3157 gen.addLoad16intoR0(20); 3158 gen.addJumpIfR0Equals(0x1, (short) -100); 3159 gen.addCountAndPassIfR0NotEquals(0x2, getCounterEnumFromOffset(-40)); 3160 gen.addLoad32intoR0(28); 3161 gen.addCountAndDropIfR0Equals(0x0, getCounterEnumFromOffset(-116)); 3162 gen.addLoadImmediate(R0, 0); 3163 gen.addCountAndPassIfBytesAtR0NotEqual(hexStringToByteArray("ffffffffffff"), getCounterEnumFromOffset(-44)); 3164 3165 gen.defineLabel((short) -100); 3166 gen.addLoadImmediate(R0, 38); 3167 gen.addCountAndDropIfBytesAtR0NotEqual(hexStringToByteArray("c0a801be"), getCounterEnumFromOffset(-68)); 3168 gen.addCountAndPass(getCounterEnumFromOffset(-8)); 3169 3170 gen.defineLabel((short) -115); 3171 gen.addLoad16intoR0(12); 3172 gen.addJumpIfR0NotEquals(0x800, (short) -263); 3173 gen.addLoad8intoR0(23); 3174 gen.addJumpIfR0NotEquals(0x11, (short) -157); 3175 gen.addLoad16intoR0(20); 3176 gen.addJumpIfR0AnyBitsSet(0x1fff, (short) -157); 3177 gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE); 3178 gen.addLoad16R1IndexedIntoR0(16); 3179 gen.addJumpIfR0NotEquals(0x44, (short) -157); 3180 gen.addLoadImmediate(R0, 50); 3181 gen.addAddR1ToR0(); 3182 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("ea42226789c0"), (short) -157); 3183 gen.addCountAndPass(getCounterEnumFromOffset(-12)); 3184 3185 gen.defineLabel((short) -157); 3186 gen.addLoad8intoR0(30); 3187 gen.addAnd(240); 3188 gen.addCountAndDropIfR0Equals(0xe0, getCounterEnumFromOffset(-84)); 3189 gen.addLoadImmediate(R1, -76); 3190 gen.addLoad32intoR0(30); 3191 gen.addJumpIfR0Equals(0xffffffff, gen.mCountAndDropLabel); 3192 gen.addCountAndDropIfR0Equals(0xc0a801ff, getCounterEnumFromOffset(-80)); 3193 gen.addLoad8intoR0(23); 3194 gen.addJumpIfR0NotEquals(0x11, (short) -243); 3195 gen.addLoadImmediate(R0, 26); 3196 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("6b7a1f1fc0a801be"), (short) -243); 3197 gen.addLoadFromMemory(R0, MemorySlot.IPV4_HEADER_SIZE); 3198 gen.addAdd(8); 3199 gen.addSwap(); 3200 gen.addLoad16intoR0(16); 3201 gen.addNeg(R1); 3202 gen.addAddR1ToR0(); 3203 gen.addJumpIfR0NotEquals(0x1, (short) -243); 3204 gen.addLoadFromMemory(R0, MemorySlot.IPV4_HEADER_SIZE); 3205 gen.addAdd(14); 3206 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("1194ceca"), (short) -243); 3207 gen.addAdd(8); 3208 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("ff"), (short) -243); 3209 gen.addCountAndDrop(getCounterEnumFromOffset(-128)); 3210 3211 gen.defineLabel((short) -243); 3212 gen.addLoadImmediate(R1, -24); 3213 gen.addLoadImmediate(R0, 0); 3214 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("ffffffffffff"), gen.mCountAndPassLabel); 3215 gen.addCountAndDrop(getCounterEnumFromOffset(-72)); 3216 gen.addCountAndPass(getCounterEnumFromOffset(-16)); 3217 3218 gen.defineLabel((short) -263); 3219 gen.addJumpIfR0Equals(0x86dd, (short) -284); 3220 gen.addLoadImmediate(R0, 0); 3221 gen.addCountAndPassIfBytesAtR0NotEqual(hexStringToByteArray("ffffffffffff"), getCounterEnumFromOffset(-48)); 3222 gen.addCountAndDrop(getCounterEnumFromOffset(-56)); 3223 3224 gen.defineLabel((short) -284); 3225 gen.addLoad8intoR0(20); 3226 gen.addJumpIfR0Equals(0x0, gen.mCountAndPassLabel); 3227 gen.addJumpIfR0Equals(0x3a, (short) -303); 3228 gen.addLoadImmediate(R1, -104); 3229 gen.addLoad8intoR0(38); 3230 gen.addJumpIfR0Equals(0xff, gen.mCountAndDropLabel); 3231 gen.addCountAndPass(getCounterEnumFromOffset(-32)); 3232 3233 gen.defineLabel((short) -303); 3234 gen.addLoad8intoR0(54); 3235 gen.addLoadImmediate(R1, -88); 3236 gen.addJumpIfR0Equals(0x85, gen.mCountAndDropLabel); 3237 gen.addJumpIfR0NotEquals(0x88, (short) -337); 3238 gen.addLoadImmediate(R0, 38); 3239 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("ff0200000000000000000000000000"), (short) -337); 3240 gen.addCountAndDrop(getCounterEnumFromOffset(-92)); 3241 3242 gen.defineLabel((short) -337); 3243 gen.addLoadImmediate(R1, -28); 3244 3245 gen.addCountTrampoline(); 3246 3247 byte[] program = gen.generate(); 3248 final String programString = toHexString(program).toLowerCase(); 3249 final String referenceProgramHexString = "6bfcb03a01b8120c6b9494014a06006b907c014388a27c013e88a47c013988b87c013488cd7c012f88e17c012a88e384003f08066a0e6bdca40110000600010800060412147a1c016bd884010400021a1c6b8c7c01010000686bd4a2ef06ffffffffffff6a266bbca2ea04c0a801be6bf872e0120c84008d08000a17821e1112149c00171fffab0d2a108210446a3239a20406ea42226789c06bf472b60a1e52f06bac7ab3e06bb41a1e7e000000a6ffffffff6bb07e0000009bc0a801ff0a178230116a1aa223086b7a1f1fc0a801beaa0d3a08aa221210ab2139821501aa0d3a0ea20a041194ceca3a08a20401ff6b8072666be868a25406ffffffffffff6bb872566bf0724c7c001086dd686bd0a23b06ffffffffffff6bc8723d0a147a32007a0b3a6b980a267a2eff6be072240a366ba87a23858218886a26a2040fff02000000000000000000000000006ba472086be4b03a01b87206b03a01b87201"; 3250 assertEquals(referenceProgramHexString, programString); 3251 } 3252 3253 @Test testInfiniteLifetimeFullApfV4ProgramGeneration()3254 public void testInfiniteLifetimeFullApfV4ProgramGeneration() throws IllegalInstructionException { 3255 ApfV4Generator gen = new ApfV4Generator(APF_VERSION_3, 1024 /* ramSize */, 3256 1024 /* clampSize */, true); 3257 gen.addLoadCounter(R0, getCounterEnumFromOffset(-8)); 3258 gen.addAdd(1); 3259 gen.addStoreData(R0, 0); 3260 gen.addLoad16intoR0(12); 3261 gen.addCountAndDropIfR0LessThan(0x600, getCounterEnumFromOffset(-120)); 3262 gen.addLoadImmediate(R1, -124); 3263 gen.addJumpIfR0Equals(0x88a2, gen.mCountAndDropLabel); 3264 gen.addJumpIfR0Equals(0x88a4, gen.mCountAndDropLabel); 3265 gen.addJumpIfR0Equals(0x88b8, gen.mCountAndDropLabel); 3266 gen.addJumpIfR0Equals(0x88cd, gen.mCountAndDropLabel); 3267 gen.addJumpIfR0Equals(0x88e1, gen.mCountAndDropLabel); 3268 gen.addJumpIfR0Equals(0x88e3, gen.mCountAndDropLabel); 3269 gen.addJumpIfR0NotEquals(0x806, (short) -122); 3270 gen.addLoadImmediate(R0, 14); 3271 gen.addCountAndDropIfBytesAtR0NotEqual(hexStringToByteArray("000108000604"), getCounterEnumFromOffset(-152)); 3272 gen.addLoad16intoR0(20); 3273 gen.addJumpIfR0Equals(0x1, (short) -104); 3274 gen.addCountAndDropIfR0NotEquals(0x2, getCounterEnumFromOffset(-156)); 3275 gen.addLoad32intoR0(28); 3276 gen.addCountAndDropIfR0Equals(0x0, getCounterEnumFromOffset(-128)); 3277 gen.addLoadImmediate(R0, 0); 3278 gen.addCountAndPassIfBytesAtR0NotEqual(hexStringToByteArray("ffffffffffff"), getCounterEnumFromOffset(-56)); 3279 3280 gen.defineLabel((short) -104); 3281 gen.addLoadImmediate(R0, 38); 3282 gen.addCountAndDropIfBytesAtR0NotEqual(hexStringToByteArray("c0a801ec"), getCounterEnumFromOffset(-80)); 3283 gen.addCountAndPass(getCounterEnumFromOffset(-20)); 3284 3285 gen.defineLabel((short) -122); 3286 gen.addLoad16intoR0(12); 3287 gen.addJumpIfR0NotEquals(0x800, (short) -249); 3288 gen.addLoad8intoR0(23); 3289 gen.addJumpIfR0NotEquals(0x11, (short) -165); 3290 gen.addLoad16intoR0(20); 3291 gen.addJumpIfR0AnyBitsSet(0x1fff, (short) -165); 3292 gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE); 3293 gen.addLoad16R1IndexedIntoR0(16); 3294 gen.addJumpIfR0NotEquals(0x44, (short) -165); 3295 gen.addLoadImmediate(R0, 50); 3296 gen.addAddR1ToR0(); 3297 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("7e9046bc7008"), (short) -165); 3298 gen.addCountAndPass(getCounterEnumFromOffset(-24)); 3299 3300 gen.defineLabel((short) -165); 3301 gen.addLoad8intoR0(30); 3302 gen.addAnd(240); 3303 gen.addCountAndDropIfR0Equals(0xe0, getCounterEnumFromOffset(-96)); 3304 gen.addLoadImmediate(R1, -88); 3305 gen.addLoad32intoR0(30); 3306 gen.addJumpIfR0Equals(0xffffffff, gen.mCountAndDropLabel); 3307 gen.addCountAndDropIfR0Equals(0xc0a801ff, getCounterEnumFromOffset(-92)); 3308 gen.addLoad8intoR0(23); 3309 gen.addJumpIfR0NotEquals(0x6, (short) -225); 3310 gen.addLoad16intoR0(20); 3311 gen.addJumpIfR0AnyBitsSet(0x1fff, (short) -225); 3312 gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE); 3313 gen.addLoad16R1IndexedIntoR0(16); 3314 gen.addJumpIfR0NotEquals(0x7, (short) -225); 3315 gen.addCountAndDrop(getCounterEnumFromOffset(-148)); 3316 3317 gen.defineLabel((short) -225); 3318 gen.addLoadImmediate(R1, -36); 3319 gen.addLoadImmediate(R0, 0); 3320 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("ffffffffffff"), gen.mCountAndPassLabel); 3321 gen.addCountAndDrop(getCounterEnumFromOffset(-84)); 3322 gen.addCountAndPass(getCounterEnumFromOffset(-28)); 3323 3324 gen.defineLabel((short) -249); 3325 gen.addJumpIfR0Equals(0x86dd, (short) -273); 3326 gen.addLoadImmediate(R0, 0); 3327 gen.addCountAndPassIfBytesAtR0NotEqual(hexStringToByteArray("ffffffffffff"), getCounterEnumFromOffset(-60)); 3328 gen.addCountAndDrop(getCounterEnumFromOffset(-68)); 3329 3330 gen.defineLabel((short) -273); 3331 gen.addLoad8intoR0(20); 3332 gen.addJumpIfR0Equals(0x0, gen.mCountAndPassLabel); 3333 gen.addJumpIfR0Equals(0x3a, (short) -297); 3334 gen.addLoadImmediate(R1, -116); 3335 gen.addLoad8intoR0(38); 3336 gen.addJumpIfR0Equals(0xff, gen.mCountAndDropLabel); 3337 gen.addCountAndPass(getCounterEnumFromOffset(-44)); 3338 3339 gen.defineLabel((short) -297); 3340 gen.addLoad8intoR0(54); 3341 gen.addCountAndDropIfR0Equals(0x85, getCounterEnumFromOffset(-100)); 3342 gen.addJumpIfR0NotEquals(0x88, (short) -333); 3343 gen.addLoadImmediate(R0, 38); 3344 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("ff0200000000000000000000000000"), (short) -333); 3345 gen.addCountAndDrop(getCounterEnumFromOffset(-104)); 3346 3347 gen.defineLabel((short) -333); 3348 gen.addLoadFromMemory(R0, MemorySlot.PACKET_SIZE); 3349 gen.addJumpIfR0NotEquals(0x96, (short) -574); 3350 gen.addLoadFromMemory(R0, MemorySlot.FILTER_AGE_SECONDS); 3351 gen.addJumpIfR0GreaterThan(0x48e, (short) -574); 3352 gen.addLoadImmediate(R0, 0); 3353 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("7e9046bc700828c68e23672c86dd60"), (short) -574); 3354 gen.addLoadImmediate(R0, 18); 3355 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("00603afffe800000000000002ac68efffe23672c"), (short) -574); 3356 gen.addLoadImmediate(R0, 54); 3357 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("8600"), (short) -574); 3358 gen.addLoadImmediate(R0, 58); 3359 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("40c0"), (short) -574); 3360 gen.addLoad16intoR0(60); 3361 gen.addJumpIfR0Equals(0x0, (short) -574); 3362 gen.addJumpIfR0LessThan(0xb4, (short) -421); 3363 gen.addJumpIfR0LessThan(0x91e, (short) -574); 3364 gen.addJumpIfR0GreaterThan(0x1b58, (short) -574); 3365 3366 gen.defineLabel((short) -421); 3367 gen.addLoadImmediate(R0, 62); 3368 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("0000000000000000010128c68e23672c05010000000005dc030440c0"), (short) -574); 3369 gen.addLoad32intoR0(90); 3370 gen.addJumpIfR0Equals(0x0, (short) -574); 3371 gen.addJumpIfR0LessThan(0xb4, (short) -480); 3372 gen.addJumpIfR0LessThan(0x55555555, (short) -574); 3373 gen.addJumpIfR0GreaterThan(0xffffffffL, (short) -574); 3374 3375 gen.defineLabel((short) -480); 3376 gen.addLoad32intoR0(94); 3377 gen.addJumpIfR0LessThan(0x55555555, (short) -574); 3378 gen.addJumpIfR0GreaterThan(0xffffffffL, (short) -574); 3379 gen.addLoadImmediate(R0, 98); 3380 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("000000002401fa000480f000000000000000000019030000"), (short) -574); 3381 gen.addLoad32intoR0(122); 3382 gen.addJumpIfR0Equals(0x0, (short) -574); 3383 gen.addJumpIfR0LessThan(0x78, (short) -547); 3384 gen.addJumpIfR0LessThan(0x91e, (short) -574); 3385 gen.addJumpIfR0GreaterThan(0x1b58, (short) -574); 3386 3387 gen.defineLabel((short) -547); 3388 gen.addLoadImmediate(R0, 126); 3389 gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("2401fa000480f00000000000000000010701"), (short) -574); 3390 gen.addCountAndDrop(getCounterEnumFromOffset(-72)); 3391 3392 gen.defineLabel((short) -574); 3393 gen.addLoadImmediate(R1, -40); 3394 3395 gen.addCountTrampoline(); 3396 3397 byte[] program = gen.generate(); 3398 final String programString = toHexString(program).toLowerCase(); 3399 final String referenceProgramHexString = "6bf8b03a01b8120c6b8894023706006b847c023088a27c022b88a47c022688b87c022188cd7c021c88e17c021788e384004608066a0e6dff68a40202000600010800060412147a1f016dff648401f500021a1c6b807c01ec0000686bc8a401d80006ffffffffffff6a266bb0a401d10004c0a801ec6bec7401c6120c84007808000a17821f1112149c00181fffab0d2a108211446a3239a205067e9046bc70086be874019b0a1e52f06ba07c019600e06ba81a1e7e00000189ffffffff6ba47e0000017ec0a801ff0a1782140612149c000d1fffab0d2a108206076dff6c7401656bdc68a401510006ffffffffffff6bac7401526be47401477c001386dd686bc4a401340006ffffffffffff6bbc7401350a147c012800007a0e3a6b8c0a267c012200ff6bd47401170a366b9c7c011400858218886a26a2040fff02000000000000000000000000006b9872f9aa0e82ec96aa0f8c00e5048e68a2d20f7e9046bc700828c68e23672c86dd606a12a2b91400603afffe800000000000002ac68efffe23672c6a36a2b20286006a3aa2ab0240c0123c7aa600920ab494009e091e8c00991b586a3ea2781c0000000000000000010128c68e23672c05010000000005dc030440c01a5a7a73009212b49600000067555555558e0000005effffffff1a5e9600000053555555558e0000004affffffff6a62a22d18000000002401fa000480f0000000000000000000190300001a7a7a2800920a78940020091e8c001b1b586a7ea204122401fa000480f000000000000000000107016bb872086bd8b03a01b87206b03a01b87201"; 3400 assertEquals(referenceProgramHexString, programString); 3401 } 3402 } 3403