1 /* 2 * Copyright (C) 2023 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 package android.net.apf 17 18 import android.content.Context 19 import android.net.LinkAddress 20 import android.net.LinkProperties 21 import android.net.MacAddress 22 import android.net.apf.ApfCounterTracker.Counter 23 import android.net.apf.ApfCounterTracker.Counter.APF_PROGRAM_ID 24 import android.net.apf.ApfCounterTracker.Counter.APF_VERSION 25 import android.net.apf.ApfCounterTracker.Counter.CORRUPT_DNS_PACKET 26 import android.net.apf.ApfCounterTracker.Counter.DROPPED_ARP_REQUEST_REPLIED 27 import android.net.apf.ApfCounterTracker.Counter.DROPPED_ETHERTYPE_NOT_ALLOWED 28 import android.net.apf.ApfCounterTracker.Counter.DROPPED_ETH_BROADCAST 29 import android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV4_NON_DHCP4 30 import android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV6_NS_INVALID 31 import android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV6_NS_OTHER_HOST 32 import android.net.apf.ApfCounterTracker.Counter.PASSED_ALLOCATE_FAILURE 33 import android.net.apf.ApfCounterTracker.Counter.PASSED_ARP 34 import android.net.apf.ApfCounterTracker.Counter.PASSED_ARP_REQUEST 35 import android.net.apf.ApfCounterTracker.Counter.PASSED_IPV4 36 import android.net.apf.ApfCounterTracker.Counter.PASSED_IPV4_FROM_DHCPV4_SERVER 37 import android.net.apf.ApfCounterTracker.Counter.PASSED_IPV6_ICMP 38 import android.net.apf.ApfCounterTracker.Counter.PASSED_IPV6_NS_MULTIPLE_OPTIONS 39 import android.net.apf.ApfCounterTracker.Counter.PASSED_IPV6_NS_NO_ADDRESS 40 import android.net.apf.ApfCounterTracker.Counter.PASSED_TRANSMIT_FAILURE 41 import android.net.apf.ApfCounterTracker.Counter.TOTAL_PACKETS 42 import android.net.apf.ApfFilter.Dependencies 43 import android.net.apf.ApfTestUtils.DROP 44 import android.net.apf.ApfTestUtils.MIN_PKT_SIZE 45 import android.net.apf.ApfTestUtils.PASS 46 import android.net.apf.ApfTestUtils.assertDrop 47 import android.net.apf.ApfTestUtils.assertPass 48 import android.net.apf.ApfTestUtils.assertVerdict 49 import android.net.apf.BaseApfGenerator.APF_VERSION_2 50 import android.net.apf.BaseApfGenerator.APF_VERSION_3 51 import android.net.apf.BaseApfGenerator.APF_VERSION_6 52 import android.net.apf.BaseApfGenerator.DROP_LABEL 53 import android.net.apf.BaseApfGenerator.IllegalInstructionException 54 import android.net.apf.BaseApfGenerator.MemorySlot 55 import android.net.apf.BaseApfGenerator.PASS_LABEL 56 import android.net.apf.BaseApfGenerator.Register.R0 57 import android.net.apf.BaseApfGenerator.Register.R1 58 import android.net.ip.IpClient.IpClientCallbacksWrapper 59 import android.os.Build 60 import android.system.OsConstants.ARPHRD_ETHER 61 import android.system.OsConstants.IFA_F_TENTATIVE 62 import androidx.test.filters.SmallTest 63 import com.android.net.module.util.HexDump 64 import com.android.net.module.util.InterfaceParams 65 import com.android.net.module.util.NetworkStackConstants.ARP_ETHER_IPV4_LEN 66 import com.android.net.module.util.NetworkStackConstants.ARP_REPLY 67 import com.android.net.module.util.NetworkStackConstants.ARP_REQUEST 68 import com.android.net.module.util.Struct 69 import com.android.net.module.util.arp.ArpPacket 70 import com.android.net.module.util.structs.EthernetHeader 71 import com.android.net.module.util.structs.Ipv4Header 72 import com.android.net.module.util.structs.UdpHeader 73 import com.android.networkstack.metrics.NetworkQuirkMetrics 74 import com.android.testutils.DevSdkIgnoreRule 75 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo 76 import com.android.testutils.DevSdkIgnoreRunner 77 import java.net.InetAddress 78 import java.nio.ByteBuffer 79 import kotlin.test.assertContentEquals 80 import kotlin.test.assertEquals 81 import kotlin.test.assertFailsWith 82 import org.junit.After 83 import org.junit.Before 84 import org.junit.Rule 85 import org.junit.Test 86 import org.junit.runner.RunWith 87 import org.mockito.ArgumentCaptor 88 import org.mockito.ArgumentMatchers.any 89 import org.mockito.Mock 90 import org.mockito.Mockito 91 import org.mockito.Mockito.times 92 import org.mockito.Mockito.verify 93 import org.mockito.Mockito.`when` 94 import org.mockito.MockitoAnnotations 95 96 const val ETH_HLEN = 14 97 const val IPV4_HLEN = 20 98 const val IPPROTO_UDP = 17 99 100 /** 101 * Tests for APF instructions. 102 */ 103 @RunWith(DevSdkIgnoreRunner::class) 104 @SmallTest 105 class ApfNewTest { 106 107 @get:Rule val ignoreRule = DevSdkIgnoreRule() 108 109 @Mock private lateinit var context: Context 110 111 @Mock private lateinit var metrics: NetworkQuirkMetrics 112 113 @Mock private lateinit var dependencies: Dependencies 114 115 @Mock private lateinit var ipClientCallback: IpClientCallbacksWrapper 116 117 private val defaultMaximumApfProgramSize = 2048 118 119 private val loInterfaceParams = InterfaceParams.getByName("lo") 120 121 private val ifParams = 122 InterfaceParams( 123 "lo", 124 loInterfaceParams.index, 125 MacAddress.fromBytes(byteArrayOf(2, 3, 4, 5, 6, 7)), 126 loInterfaceParams.defaultMtu 127 ) 128 129 private val testPacket = byteArrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16) 130 private val hostIpv4Address = byteArrayOf(10, 0, 0, 1) 131 private val senderIpv4Address = byteArrayOf(10, 0, 0, 2) 132 private val arpBroadcastMacAddress = intArrayOf(0xff, 0xff, 0xff, 0xff, 0xff, 0xff) <lambda>null133 .map { it.toByte() }.toByteArray() 134 private val senderMacAddress = intArrayOf(0x01, 0x22, 0x33, 0x44, 0x55, 0x66) <lambda>null135 .map { it.toByte() }.toByteArray() 136 private val hostIpv6Addresses = listOf( 137 // 2001::200:1a:3344:1122 138 intArrayOf(0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x02, 0, 0, 0x1a, 0x33, 0x44, 0x11, 0x22) <lambda>null139 .map{ it.toByte() }.toByteArray(), 140 // 2001::100:1b:4455:6677 141 intArrayOf(0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x01, 0, 0, 0x1b, 0x44, 0x55, 0x66, 0x77) <lambda>null142 .map{ it.toByte() }.toByteArray() 143 ) 144 private val hostIpv6TentativeAddresses = listOf( 145 // 2001::200:1a:1234:5678 146 intArrayOf(0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x02, 0, 0, 0x1a, 0x12, 0x34, 0x56, 0x78) <lambda>null147 .map{ it.toByte() }.toByteArray(), 148 // 2001::100:1b:1234:5678 149 intArrayOf(0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x01, 0, 0, 0x1b, 0x12, 0x34, 0x56, 0x78) <lambda>null150 .map{ it.toByte() }.toByteArray() 151 ) 152 private val hostAnycast6Addresses = listOf( 153 // 2001::100:1b:aabb:ccdd 154 intArrayOf(0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x01, 0, 0, 0x1b, 0xaa, 0xbb, 0xcc, 0xdd) <lambda>null155 .map{ it.toByte() }.toByteArray() 156 ) 157 private val hostMulticastMacAddresses = listOf( 158 // 33:33:00:00:00:01 <lambda>null159 intArrayOf(0x33, 0x33, 0, 0, 0, 1).map { it.toByte() }.toByteArray(), 160 // 33:33:ff:44:11:22 <lambda>null161 intArrayOf(0x33, 0x33, 0xff, 0x44, 0x11, 0x22).map { it.toByte() }.toByteArray(), 162 // 33:33:ff:55:66:77 <lambda>null163 intArrayOf(0x33, 0x33, 0xff, 0x55, 0x66, 0x77).map { it.toByte() }.toByteArray(), 164 // 33:33:ff:bb:cc:dd <lambda>null165 intArrayOf(0x33, 0x33, 0xff, 0xbb, 0xcc, 0xdd).map { it.toByte() }.toByteArray(), 166 ) 167 @Before setUpnull168 fun setUp() { 169 MockitoAnnotations.initMocks(this) 170 // mock anycast6 address from /proc/net/anycast6 171 `when`(dependencies.getAnycast6Addresses(any())).thenReturn(hostAnycast6Addresses) 172 // mock host mac address and ethernet multicast addresses from /proc/net/dev_mcast 173 `when`(dependencies.getEtherMulticastAddresses(any())).thenReturn(hostMulticastMacAddresses) 174 } 175 176 @After tearDownnull177 fun tearDown() { 178 Mockito.framework().clearInlineMocks() 179 ApfJniUtils.resetTransmittedPacketMemory() 180 } 181 182 @Test testDataInstructionMustComeFirstnull183 fun testDataInstructionMustComeFirst() { 184 var gen = ApfV6Generator(defaultMaximumApfProgramSize) 185 gen.addAllocateR0() 186 assertFailsWith<IllegalInstructionException> { gen.addData(ByteArray(3) { 0x01 }) } 187 } 188 189 @Test testApfInstructionEncodingSizeChecknull190 fun testApfInstructionEncodingSizeCheck() { 191 var gen = ApfV6Generator(defaultMaximumApfProgramSize) 192 assertFailsWith<IllegalArgumentException> { 193 ApfV6Generator(ByteArray(65536) { 0x01 }, defaultMaximumApfProgramSize) 194 } 195 assertFailsWith<IllegalArgumentException> { gen.addAllocate(65536) } 196 assertFailsWith<IllegalArgumentException> { gen.addAllocate(-1) } 197 assertFailsWith<IllegalArgumentException> { gen.addDataCopy(-1, 1) } 198 assertFailsWith<IllegalArgumentException> { gen.addPacketCopy(-1, 1) } 199 assertFailsWith<IllegalArgumentException> { gen.addDataCopy(1, 256) } 200 assertFailsWith<IllegalArgumentException> { gen.addPacketCopy(1, 256) } 201 assertFailsWith<IllegalArgumentException> { gen.addDataCopy(1, -1) } 202 assertFailsWith<IllegalArgumentException> { gen.addPacketCopy(1, -1) } 203 assertFailsWith<IllegalArgumentException> { gen.addPacketCopyFromR0(256) } 204 assertFailsWith<IllegalArgumentException> { gen.addDataCopyFromR0(256) } 205 assertFailsWith<IllegalArgumentException> { gen.addPacketCopyFromR0(-1) } 206 assertFailsWith<IllegalArgumentException> { gen.addDataCopyFromR0(-1) } 207 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsQ( 208 byteArrayOf(1, 'A'.code.toByte(), 0, 0), 209 256, 210 ApfV4Generator.DROP_LABEL 211 ) } 212 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsQ( 213 byteArrayOf(1, 'a'.code.toByte(), 0, 0), 214 0x0c, 215 ApfV4Generator.DROP_LABEL 216 ) } 217 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsQ( 218 byteArrayOf(1, '.'.code.toByte(), 0, 0), 219 0x0c, 220 ApfV4Generator.DROP_LABEL 221 ) } 222 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsQ( 223 byteArrayOf(0, 0), 224 0xc0, 225 ApfV4Generator.DROP_LABEL 226 ) } 227 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsQ( 228 byteArrayOf(1, 'A'.code.toByte()), 229 0xc0, 230 ApfV4Generator.DROP_LABEL 231 ) } 232 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsQ( 233 byteArrayOf(64) + ByteArray(64) { 'A'.code.toByte() } + byteArrayOf(0, 0), 234 0xc0, 235 ApfV4Generator.DROP_LABEL 236 ) } 237 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsQ( 238 byteArrayOf(1, 'A'.code.toByte(), 1, 'B'.code.toByte(), 0), 239 0xc0, 240 ApfV4Generator.DROP_LABEL 241 ) } 242 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsQ( 243 byteArrayOf(1, 'A'.code.toByte(), 1, 'B'.code.toByte()), 244 0xc0, 245 ApfV4Generator.DROP_LABEL 246 ) } 247 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsQ( 248 byteArrayOf(1, 'A'.code.toByte(), 0, 0), 249 256, 250 ApfV4Generator.DROP_LABEL 251 ) } 252 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsQ( 253 byteArrayOf(1, 'a'.code.toByte(), 0, 0), 254 0x0c, 255 ApfV4Generator.DROP_LABEL 256 ) } 257 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsQ( 258 byteArrayOf(1, '.'.code.toByte(), 0, 0), 259 0x0c, 260 ApfV4Generator.DROP_LABEL 261 ) } 262 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsQ( 263 byteArrayOf(0, 0), 264 0xc0, 265 ApfV4Generator.DROP_LABEL 266 ) } 267 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsQ( 268 byteArrayOf(1, 'A'.code.toByte()), 269 0xc0, 270 ApfV4Generator.DROP_LABEL 271 ) } 272 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsQ( 273 byteArrayOf(64) + ByteArray(64) { 'A'.code.toByte() } + byteArrayOf(0, 0), 274 0xc0, 275 ApfV4Generator.DROP_LABEL 276 ) } 277 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsQ( 278 byteArrayOf(1, 'A'.code.toByte(), 1, 'B'.code.toByte(), 0), 279 0xc0, 280 ApfV4Generator.DROP_LABEL 281 ) } 282 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsQ( 283 byteArrayOf(1, 'A'.code.toByte(), 1, 'B'.code.toByte()), 284 0xc0, 285 ApfV4Generator.DROP_LABEL 286 ) } 287 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsA( 288 byteArrayOf(1, 'a'.code.toByte(), 0, 0), 289 ApfV4Generator.DROP_LABEL 290 ) } 291 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsA( 292 byteArrayOf(1, '.'.code.toByte(), 0, 0), 293 ApfV4Generator.DROP_LABEL 294 ) } 295 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsA( 296 byteArrayOf(0, 0), 297 ApfV4Generator.DROP_LABEL 298 ) } 299 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsA( 300 byteArrayOf(1, 'A'.code.toByte()), 301 ApfV4Generator.DROP_LABEL 302 ) } 303 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsA( 304 byteArrayOf(64) + ByteArray(64) { 'A'.code.toByte() } + byteArrayOf(0, 0), 305 ApfV4Generator.DROP_LABEL 306 ) } 307 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsA( 308 byteArrayOf(1, 'A'.code.toByte(), 1, 'B'.code.toByte(), 0), 309 ApfV4Generator.DROP_LABEL 310 ) } 311 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0DoesNotContainDnsA( 312 byteArrayOf(1, 'A'.code.toByte(), 1, 'B'.code.toByte()), 313 ApfV4Generator.DROP_LABEL 314 ) } 315 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsA( 316 byteArrayOf(1, 'a'.code.toByte(), 0, 0), 317 ApfV4Generator.DROP_LABEL 318 ) } 319 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsA( 320 byteArrayOf(1, '.'.code.toByte(), 0, 0), 321 ApfV4Generator.DROP_LABEL 322 ) } 323 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsA( 324 byteArrayOf(0, 0), 325 ApfV4Generator.DROP_LABEL 326 ) } 327 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsA( 328 byteArrayOf(1, 'A'.code.toByte()), 329 ApfV4Generator.DROP_LABEL 330 ) } 331 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsA( 332 byteArrayOf(64) + ByteArray(64) { 'A'.code.toByte() } + byteArrayOf(0, 0), 333 ApfV4Generator.DROP_LABEL 334 ) } 335 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsA( 336 byteArrayOf(1, 'A'.code.toByte(), 1, 'B'.code.toByte(), 0), 337 ApfV4Generator.DROP_LABEL 338 ) } 339 assertFailsWith<IllegalArgumentException> { gen.addJumpIfPktAtR0ContainDnsA( 340 byteArrayOf(1, 'A'.code.toByte(), 1, 'B'.code.toByte()), 341 ApfV4Generator.DROP_LABEL 342 ) } 343 assertFailsWith<IllegalArgumentException> { 344 gen.addJumpIfBytesAtR0Equal(ByteArray(2048) { 1 }, DROP_LABEL) 345 } 346 assertFailsWith<IllegalArgumentException> { 347 gen.addJumpIfBytesAtR0NotEqual(ByteArray(2048) { 1 }, DROP_LABEL) 348 } 349 assertFailsWith<IllegalArgumentException> { gen.addCountAndDrop(PASSED_ARP) } 350 assertFailsWith<IllegalArgumentException> { gen.addCountAndPass(DROPPED_ETH_BROADCAST) } 351 assertFailsWith<IllegalArgumentException> { 352 gen.addCountAndDropIfR0Equals(3, PASSED_ARP) 353 } 354 assertFailsWith<IllegalArgumentException> { 355 gen.addCountAndPassIfR0Equals(3, DROPPED_ETH_BROADCAST) 356 } 357 assertFailsWith<IllegalArgumentException> { 358 gen.addCountAndDropIfR0NotEquals(3, PASSED_ARP) 359 } 360 assertFailsWith<IllegalArgumentException> { 361 gen.addCountAndPassIfR0NotEquals(3, DROPPED_ETH_BROADCAST) 362 } 363 assertFailsWith<IllegalArgumentException> { 364 gen.addCountAndDropIfR0LessThan(3, PASSED_ARP) 365 } 366 assertFailsWith<IllegalArgumentException> { 367 gen.addCountAndPassIfR0LessThan(3, DROPPED_ETH_BROADCAST) 368 } 369 assertFailsWith<IllegalArgumentException> { 370 gen.addCountAndDropIfR0GreaterThan(3, PASSED_ARP) 371 } 372 assertFailsWith<IllegalArgumentException> { 373 gen.addCountAndPassIfR0GreaterThan(3, DROPPED_ETH_BROADCAST) 374 } 375 assertFailsWith<IllegalArgumentException> { 376 gen.addCountAndDropIfBytesAtR0NotEqual(byteArrayOf(1), PASSED_ARP) 377 } 378 assertFailsWith<IllegalArgumentException> { 379 gen.addCountAndDropIfBytesAtR0Equal(byteArrayOf(1), PASSED_ARP) 380 } 381 assertFailsWith<IllegalArgumentException> { 382 gen.addCountAndPassIfBytesAtR0Equal(byteArrayOf(1), DROPPED_ETH_BROADCAST) 383 } 384 assertFailsWith<IllegalArgumentException> { 385 gen.addCountAndDropIfR0AnyBitsSet(3, PASSED_ARP) 386 } 387 assertFailsWith<IllegalArgumentException> { 388 gen.addCountAndPassIfR0AnyBitsSet(3, DROPPED_ETH_BROADCAST) 389 } 390 assertFailsWith<IllegalArgumentException> { 391 gen.addCountAndDropIfR0IsOneOf(setOf(3), PASSED_ARP) 392 } 393 assertFailsWith<IllegalArgumentException> { 394 gen.addCountAndPassIfR0IsOneOf(setOf(3), DROPPED_ETH_BROADCAST) 395 } 396 assertFailsWith<IllegalArgumentException> { 397 gen.addCountAndDropIfR0IsNoneOf(setOf(3), PASSED_ARP) 398 } 399 assertFailsWith<IllegalArgumentException> { 400 gen.addCountAndPassIfR0IsNoneOf(setOf(3), DROPPED_ETH_BROADCAST) 401 } 402 assertFailsWith<IllegalArgumentException> { 403 gen.addCountAndDropIfBytesAtR0EqualsAnyOf(listOf(byteArrayOf(1)), PASSED_ARP) 404 } 405 assertFailsWith<IllegalArgumentException> { 406 gen.addCountAndPassIfBytesAtR0EqualsAnyOf(listOf(byteArrayOf(1)), DROPPED_ETH_BROADCAST) 407 } 408 assertFailsWith<IllegalArgumentException> { 409 gen.addCountAndDropIfBytesAtR0EqualsNoneOf(listOf(byteArrayOf(1)), PASSED_ARP) 410 } 411 assertFailsWith<IllegalArgumentException> { 412 gen.addCountAndPassIfBytesAtR0EqualsNoneOf( 413 listOf(byteArrayOf(1)), 414 DROPPED_ETH_BROADCAST 415 ) 416 } 417 assertFailsWith<IllegalArgumentException> { 418 gen.addWrite32(byteArrayOf()) 419 } 420 assertFailsWith<IllegalArgumentException> { 421 gen.addJumpIfOneOf(R0, setOf(), PASS_LABEL) 422 } 423 assertFailsWith<IllegalArgumentException> { 424 gen.addJumpIfOneOf(R0, setOf(-1, 1), PASS_LABEL) 425 } 426 assertFailsWith<IllegalArgumentException> { 427 gen.addJumpIfOneOf(R0, setOf(4294967296L, 1), PASS_LABEL) 428 } 429 assertFailsWith<IllegalArgumentException> { 430 gen.addJumpIfOneOf(R0, List(34) { (it + 1).toLong() }.toSet(), PASS_LABEL) 431 } 432 assertFailsWith<IllegalArgumentException> { 433 gen.addJumpIfBytesAtR0EqualsAnyOf(listOf(ByteArray(2048) { 1 }), PASS_LABEL ) 434 } 435 assertFailsWith<IllegalArgumentException> { 436 gen.addJumpIfBytesAtR0EqualsAnyOf( 437 listOf(byteArrayOf(1), byteArrayOf(1, 2)), 438 PASS_LABEL 439 ) 440 } 441 442 val v4gen = ApfV4Generator(APF_VERSION_3) 443 assertFailsWith<IllegalArgumentException> { v4gen.addCountAndDrop(PASSED_ARP) } 444 assertFailsWith<IllegalArgumentException> { v4gen.addCountAndPass(DROPPED_ETH_BROADCAST) } 445 assertFailsWith<IllegalArgumentException> { 446 v4gen.addCountAndDropIfR0Equals(3, PASSED_ARP) 447 } 448 assertFailsWith<IllegalArgumentException> { 449 v4gen.addCountAndPassIfR0Equals(3, DROPPED_ETH_BROADCAST) 450 } 451 assertFailsWith<IllegalArgumentException> { 452 v4gen.addCountAndDropIfR0NotEquals(3, PASSED_ARP) 453 } 454 assertFailsWith<IllegalArgumentException> { 455 v4gen.addCountAndPassIfR0NotEquals(3, DROPPED_ETH_BROADCAST) 456 } 457 assertFailsWith<IllegalArgumentException> { 458 v4gen.addCountAndDropIfBytesAtR0Equal(byteArrayOf(1), PASSED_ARP) 459 } 460 assertFailsWith<IllegalArgumentException> { 461 v4gen.addCountAndPassIfBytesAtR0Equal(byteArrayOf(1), DROPPED_ETH_BROADCAST) 462 } 463 assertFailsWith<IllegalArgumentException> { 464 v4gen.addCountAndDropIfR0LessThan(3, PASSED_ARP) 465 } 466 assertFailsWith<IllegalArgumentException> { 467 v4gen.addCountAndPassIfR0LessThan(3, DROPPED_ETH_BROADCAST) 468 } 469 assertFailsWith<IllegalArgumentException> { 470 v4gen.addCountAndDropIfR0GreaterThan(3, PASSED_ARP) 471 } 472 assertFailsWith<IllegalArgumentException> { 473 v4gen.addCountAndPassIfR0GreaterThan(3, DROPPED_ETH_BROADCAST) 474 } 475 assertFailsWith<IllegalArgumentException> { 476 v4gen.addCountAndDropIfBytesAtR0NotEqual(byteArrayOf(1), PASSED_ARP) 477 } 478 assertFailsWith<IllegalArgumentException> { 479 v4gen.addCountAndDropIfR0AnyBitsSet(3, PASSED_ARP) 480 } 481 assertFailsWith<IllegalArgumentException> { 482 v4gen.addCountAndPassIfR0AnyBitsSet(3, DROPPED_ETH_BROADCAST) 483 } 484 assertFailsWith<IllegalArgumentException> { 485 v4gen.addCountAndDropIfR0IsOneOf(setOf(3), PASSED_ARP) 486 } 487 assertFailsWith<IllegalArgumentException> { 488 v4gen.addCountAndPassIfR0IsOneOf(setOf(3), DROPPED_ETH_BROADCAST) 489 } 490 assertFailsWith<IllegalArgumentException> { 491 v4gen.addCountAndDropIfR0IsNoneOf(setOf(3), PASSED_ARP) 492 } 493 assertFailsWith<IllegalArgumentException> { 494 v4gen.addCountAndPassIfR0IsNoneOf(setOf(3), DROPPED_ETH_BROADCAST) 495 } 496 assertFailsWith<IllegalArgumentException> { 497 v4gen.addCountAndDropIfBytesAtR0EqualsAnyOf(listOf(byteArrayOf(1)), PASSED_ARP) 498 } 499 assertFailsWith<IllegalArgumentException> { 500 v4gen.addCountAndPassIfBytesAtR0EqualsAnyOf( 501 listOf(byteArrayOf(1)), 502 DROPPED_ETH_BROADCAST 503 ) 504 } 505 assertFailsWith<IllegalArgumentException> { 506 v4gen.addCountAndDropIfBytesAtR0EqualsNoneOf(listOf(byteArrayOf(1)), PASSED_ARP) 507 } 508 assertFailsWith<IllegalArgumentException> { 509 v4gen.addCountAndPassIfBytesAtR0EqualsNoneOf( 510 listOf(byteArrayOf(1)), 511 DROPPED_ETH_BROADCAST 512 ) 513 } 514 } 515 516 @Test testValidateDnsNamesnull517 fun testValidateDnsNames() { 518 // '%' is a valid label character in mDNS subtype 519 // byte == 0xff means it is a '*' wildcard, which is a valid encoding. 520 val program = ApfV6Generator(defaultMaximumApfProgramSize).addJumpIfPktAtR0ContainDnsQ( 521 byteArrayOf(1, '%'.code.toByte(), 0, 0), 522 1, 523 DROP_LABEL 524 ).addJumpIfPktAtR0ContainDnsA( 525 byteArrayOf(0xff.toByte(), 1, 'B'.code.toByte(), 0, 0), 526 DROP_LABEL 527 ).generate() 528 } 529 530 @Test testApfInstructionsEncodingnull531 fun testApfInstructionsEncoding() { 532 val v4gen = ApfV4Generator(APF_VERSION_2) 533 v4gen.addPass() 534 var program = v4gen.generate() 535 // encoding PASS opcode: opcode=0, imm_len=0, R=0 536 assertContentEquals( 537 byteArrayOf(encodeInstruction(opcode = 0, immLength = 0, register = 0)), 538 program 539 ) 540 assertContentEquals( 541 listOf("0: pass"), 542 ApfJniUtils.disassembleApf(program).map { it.trim() } 543 ) 544 545 var gen = ApfV6Generator(defaultMaximumApfProgramSize) 546 gen.addDrop() 547 program = gen.generate().skipDataAndDebug() 548 // encoding DROP opcode: opcode=0, imm_len=0, R=1 549 assertContentEquals( 550 byteArrayOf(encodeInstruction(opcode = 0, immLength = 0, register = 1)), 551 program 552 ) 553 assertContentEquals( 554 listOf("0: drop"), 555 ApfJniUtils.disassembleApf(program).map { it.trim() } 556 ) 557 558 gen = ApfV6Generator(defaultMaximumApfProgramSize) 559 gen.addCountAndPass(129) 560 program = gen.generate().skipDataAndDebug() 561 // encoding COUNT(PASS) opcode: opcode=0, imm_len=size_of(imm), R=0, imm=counterNumber 562 assertContentEquals( 563 byteArrayOf( 564 encodeInstruction(opcode = 0, immLength = 1, register = 0), 565 0x81.toByte() 566 ), 567 program 568 ) 569 assertContentEquals( 570 listOf("0: pass counter=129"), 571 ApfJniUtils.disassembleApf(program).map { it.trim() } 572 ) 573 574 gen = ApfV6Generator(defaultMaximumApfProgramSize) 575 gen.addCountAndDrop(1000) 576 program = gen.generate().skipDataAndDebug() 577 // encoding COUNT(DROP) opcode: opcode=0, imm_len=size_of(imm), R=1, imm=counterNumber 578 assertContentEquals( 579 byteArrayOf( 580 encodeInstruction(opcode = 0, immLength = 2, register = 1), 581 0x03, 582 0xe8.toByte() 583 ), 584 program 585 ) 586 assertContentEquals( 587 listOf("0: drop counter=1000"), 588 ApfJniUtils.disassembleApf(program).map { it.trim() } 589 ) 590 591 gen = ApfV6Generator(defaultMaximumApfProgramSize) 592 gen.addCountAndPass(PASSED_ARP) 593 program = gen.generate().skipDataAndDebug() 594 // encoding COUNT(PASS) opcode: opcode=0, imm_len=size_of(imm), R=0, imm=counterNumber 595 assertContentEquals( 596 byteArrayOf( 597 encodeInstruction(opcode = 0, immLength = 1, register = 0), 598 PASSED_ARP.value().toByte() 599 ), 600 program 601 ) 602 assertContentEquals( 603 listOf("0: pass counter=10"), 604 ApfJniUtils.disassembleApf(program).map { it.trim() } 605 ) 606 607 gen = ApfV6Generator(defaultMaximumApfProgramSize) 608 gen.addCountAndDrop(DROPPED_ETHERTYPE_NOT_ALLOWED) 609 program = gen.generate().skipDataAndDebug() 610 // encoding COUNT(DROP) opcode: opcode=0, imm_len=size_of(imm), R=1, imm=counterNumber 611 assertContentEquals( 612 byteArrayOf( 613 encodeInstruction(opcode = 0, immLength = 1, register = 1), 614 DROPPED_ETHERTYPE_NOT_ALLOWED.value().toByte() 615 ), 616 program 617 ) 618 assertContentEquals( 619 listOf("0: drop counter=43"), 620 ApfJniUtils.disassembleApf(program).map { it.trim() } 621 ) 622 623 gen = ApfV6Generator(defaultMaximumApfProgramSize) 624 gen.addAllocateR0() 625 gen.addAllocate(1500) 626 program = gen.generate().skipDataAndDebug() 627 // encoding ALLOC opcode: opcode=21(EXT opcode number), imm=36(TRANS opcode number). 628 // R=0 means length stored in R0. R=1 means the length stored in imm1. 629 assertContentEquals( 630 byteArrayOf( 631 encodeInstruction(opcode = 21, immLength = 1, register = 0), 632 36, 633 encodeInstruction(opcode = 21, immLength = 1, register = 1), 634 36, 635 0x05, 636 0xDC.toByte() 637 ), 638 program 639 ) 640 assertContentEquals(listOf( 641 "0: allocate r0", 642 "2: allocate 1500" 643 ), ApfJniUtils.disassembleApf(program).map { it.trim() }) 644 645 gen = ApfV6Generator(defaultMaximumApfProgramSize) 646 gen.addTransmitWithoutChecksum() 647 gen.addTransmitL4(30, 40, 50, 256, true) 648 program = gen.generate().skipDataAndDebug() 649 // encoding TRANSMIT opcode: opcode=21(EXT opcode number), 650 // imm=37(TRANSMIT opcode number), 651 assertContentEquals(byteArrayOf( 652 encodeInstruction(opcode = 21, immLength = 1, register = 0), 653 37, 255.toByte(), 255.toByte(), 654 encodeInstruction(opcode = 21, immLength = 1, register = 1), 37, 30, 40, 50, 1, 0 655 ), program) 656 assertContentEquals(listOf( 657 "0: transmit ip_ofs=255", 658 "4: transmitudp ip_ofs=30, csum_ofs=40, csum_start=50, partial_csum=0x0100", 659 ), ApfJniUtils.disassembleApf(program).map { it.trim() }) 660 661 val largeByteArray = ByteArray(256) { 0x01 } 662 gen = ApfV6Generator(largeByteArray, defaultMaximumApfProgramSize) 663 program = gen.generate() 664 assertContentEquals( 665 byteArrayOf( 666 encodeInstruction(opcode = 14, immLength = 2, register = 1), 1, 0 667 ) + largeByteArray + byteArrayOf( 668 encodeInstruction(opcode = 21, immLength = 1, register = 0), 48, 6, 25 669 ), 670 program 671 ) 672 assertContentEquals( 673 listOf( 674 "0: data 256, " + "01".repeat(256), 675 "259: debugbuf size=1561" 676 ), 677 ApfJniUtils.disassembleApf(program).map { it.trim() } 678 ) 679 680 gen = ApfV6Generator(defaultMaximumApfProgramSize) 681 gen.addWriteU8(0x01) 682 gen.addWriteU16(0x0102) 683 gen.addWriteU32(0x01020304) 684 gen.addWriteU8(0x00) 685 gen.addWriteU8(0x80) 686 gen.addWriteU16(0x0000) 687 gen.addWriteU16(0x8000) 688 gen.addWriteU32(0x00000000) 689 gen.addWriteU32(0x80000000) 690 gen.addWrite32(-2) 691 gen.addWrite32(byteArrayOf(0xff.toByte(), 0xfe.toByte(), 0xfd.toByte(), 0xfc.toByte())) 692 program = gen.generate().skipDataAndDebug() 693 assertContentEquals(byteArrayOf( 694 encodeInstruction(24, 1, 0), 0x01, 695 encodeInstruction(24, 2, 0), 0x01, 0x02, 696 encodeInstruction(24, 4, 0), 0x01, 0x02, 0x03, 0x04, 697 encodeInstruction(24, 1, 0), 0x00, 698 encodeInstruction(24, 1, 0), 0x80.toByte(), 699 encodeInstruction(24, 2, 0), 0x00, 0x00, 700 encodeInstruction(24, 2, 0), 0x80.toByte(), 0x00, 701 encodeInstruction(24, 4, 0), 0x00, 0x00, 0x00, 0x00, 702 encodeInstruction(24, 4, 0), 0x80.toByte(), 0x00, 0x00, 0x00, 703 encodeInstruction(24, 4, 0), 0xff.toByte(), 0xff.toByte(), 704 0xff.toByte(), 0xfe.toByte(), 705 encodeInstruction(24, 4, 0), 0xff.toByte(), 0xfe.toByte(), 706 0xfd.toByte(), 0xfc.toByte()), program) 707 assertContentEquals(listOf( 708 "0: write 0x01", 709 "2: write 0x0102", 710 "5: write 0x01020304", 711 "10: write 0x00", 712 "12: write 0x80", 713 "14: write 0x0000", 714 "17: write 0x8000", 715 "20: write 0x00000000", 716 "25: write 0x80000000", 717 "30: write 0xfffffffe", 718 "35: write 0xfffefdfc" 719 ), ApfJniUtils.disassembleApf(program).map { it.trim() }) 720 721 gen = ApfV6Generator(defaultMaximumApfProgramSize) 722 gen.addWriteU8(R0) 723 gen.addWriteU16(R0) 724 gen.addWriteU32(R0) 725 gen.addWriteU8(R1) 726 gen.addWriteU16(R1) 727 gen.addWriteU32(R1) 728 program = gen.generate().skipDataAndDebug() 729 assertContentEquals(byteArrayOf( 730 encodeInstruction(21, 1, 0), 38, 731 encodeInstruction(21, 1, 0), 39, 732 encodeInstruction(21, 1, 0), 40, 733 encodeInstruction(21, 1, 1), 38, 734 encodeInstruction(21, 1, 1), 39, 735 encodeInstruction(21, 1, 1), 40 736 ), program) 737 assertContentEquals(listOf( 738 "0: ewrite1 r0", 739 "2: ewrite2 r0", 740 "4: ewrite4 r0", 741 "6: ewrite1 r1", 742 "8: ewrite2 r1", 743 "10: ewrite4 r1" 744 ), ApfJniUtils.disassembleApf(program).map { it.trim() }) 745 746 gen = ApfV6Generator(defaultMaximumApfProgramSize) 747 gen.addDataCopy(0, 10) 748 gen.addDataCopy(1, 5) 749 gen.addPacketCopy(1000, 255) 750 program = gen.generate().skipDataAndDebug() 751 assertContentEquals(byteArrayOf( 752 encodeInstruction(25, 0, 1), 10, 753 encodeInstruction(25, 1, 1), 1, 5, 754 encodeInstruction(25, 2, 0), 755 0x03.toByte(), 0xe8.toByte(), 0xff.toByte(), 756 ), program) 757 assertContentEquals(listOf( 758 "0: datacopy src=0, len=10", 759 "2: datacopy src=1, len=5", 760 "5: pktcopy src=1000, len=255" 761 ), ApfJniUtils.disassembleApf(program).map { it.trim() }) 762 763 gen = ApfV6Generator(defaultMaximumApfProgramSize) 764 gen.addDataCopyFromR0(5) 765 gen.addPacketCopyFromR0(5) 766 gen.addDataCopyFromR0LenR1() 767 gen.addPacketCopyFromR0LenR1() 768 program = gen.generate().skipDataAndDebug() 769 assertContentEquals(byteArrayOf( 770 encodeInstruction(21, 1, 1), 41, 5, 771 encodeInstruction(21, 1, 0), 41, 5, 772 encodeInstruction(21, 1, 1), 42, 773 encodeInstruction(21, 1, 0), 42, 774 ), program) 775 assertContentEquals(listOf( 776 "0: edatacopy src=r0, len=5", 777 "3: epktcopy src=r0, len=5", 778 "6: edatacopy src=r0, len=r1", 779 "8: epktcopy src=r0, len=r1" 780 ), ApfJniUtils.disassembleApf(program).map{ it.trim() }) 781 782 gen = ApfV6Generator(defaultMaximumApfProgramSize) 783 gen.addJumpIfBytesAtR0Equal(byteArrayOf('a'.code.toByte()), ApfV4Generator.DROP_LABEL) 784 program = gen.generate().skipDataAndDebug() 785 assertContentEquals(byteArrayOf( 786 encodeInstruction(opcode = 20, immLength = 1, register = 1), 787 1, 788 1, 789 'a'.code.toByte() 790 ), program) 791 assertContentEquals(listOf( 792 "0: jbseq r0, 0x1, DROP, 61" 793 ), ApfJniUtils.disassembleApf(program).map{ it.trim() }) 794 795 val qnames = byteArrayOf(1, 'A'.code.toByte(), 1, 'B'.code.toByte(), 0, 0) 796 gen = ApfV6Generator(defaultMaximumApfProgramSize) 797 gen.addJumpIfPktAtR0DoesNotContainDnsQ(qnames, 0x0c, ApfV4Generator.DROP_LABEL) 798 gen.addJumpIfPktAtR0ContainDnsQ(qnames, 0x0c, ApfV4Generator.DROP_LABEL) 799 program = gen.generate().skipDataAndDebug() 800 assertContentEquals(byteArrayOf( 801 encodeInstruction(21, 1, 0), 43, 11, 0x0c.toByte(), 802 ) + qnames + byteArrayOf( 803 encodeInstruction(21, 1, 1), 43, 1, 0x0c.toByte(), 804 ) + qnames, program) 805 assertContentEquals(listOf( 806 "0: jdnsqne r0, DROP, 12, (1)A(1)B(0)(0)", 807 "10: jdnsqeq r0, DROP, 12, (1)A(1)B(0)(0)" 808 ), ApfJniUtils.disassembleApf(program).map{ it.trim() }) 809 810 gen = ApfV6Generator(defaultMaximumApfProgramSize) 811 gen.addJumpIfPktAtR0DoesNotContainDnsQSafe(qnames, 0x0c, ApfV4Generator.DROP_LABEL) 812 gen.addJumpIfPktAtR0ContainDnsQSafe(qnames, 0x0c, ApfV4Generator.DROP_LABEL) 813 program = gen.generate().skipDataAndDebug() 814 assertContentEquals(byteArrayOf( 815 encodeInstruction(21, 1, 0), 45, 11, 0x0c.toByte(), 816 ) + qnames + byteArrayOf( 817 encodeInstruction(21, 1, 1), 45, 1, 0x0c.toByte(), 818 ) + qnames, program) 819 assertContentEquals(listOf( 820 "0: jdnsqnesafe r0, DROP, 12, (1)A(1)B(0)(0)", 821 "10: jdnsqeqsafe r0, DROP, 12, (1)A(1)B(0)(0)" 822 ), ApfJniUtils.disassembleApf(program).map{ it.trim() }) 823 824 gen = ApfV6Generator(defaultMaximumApfProgramSize) 825 gen.addJumpIfPktAtR0DoesNotContainDnsA(qnames, ApfV4Generator.DROP_LABEL) 826 gen.addJumpIfPktAtR0ContainDnsA(qnames, ApfV4Generator.DROP_LABEL) 827 program = gen.generate().skipDataAndDebug() 828 assertContentEquals(byteArrayOf( 829 encodeInstruction(21, 1, 0), 44, 10, 830 ) + qnames + byteArrayOf( 831 encodeInstruction(21, 1, 1), 44, 1, 832 ) + qnames, program) 833 assertContentEquals(listOf( 834 "0: jdnsane r0, DROP, (1)A(1)B(0)(0)", 835 "9: jdnsaeq r0, DROP, (1)A(1)B(0)(0)" 836 ), ApfJniUtils.disassembleApf(program).map{ it.trim() }) 837 838 gen = ApfV6Generator(defaultMaximumApfProgramSize) 839 gen.addJumpIfPktAtR0DoesNotContainDnsASafe(qnames, ApfV4Generator.DROP_LABEL) 840 gen.addJumpIfPktAtR0ContainDnsASafe(qnames, ApfV4Generator.DROP_LABEL) 841 program = gen.generate().skipDataAndDebug() 842 assertContentEquals(byteArrayOf( 843 encodeInstruction(21, 1, 0), 46, 10, 844 ) + qnames + byteArrayOf( 845 encodeInstruction(21, 1, 1), 46, 1, 846 ) + qnames, program) 847 assertContentEquals(listOf( 848 "0: jdnsanesafe r0, DROP, (1)A(1)B(0)(0)", 849 "9: jdnsaeqsafe r0, DROP, (1)A(1)B(0)(0)" 850 ), ApfJniUtils.disassembleApf(program).map{ it.trim() }) 851 852 gen = ApfV6Generator(defaultMaximumApfProgramSize) 853 gen.addJumpIfOneOf(R1, List(32) { (it + 1).toLong() }.toSet(), DROP_LABEL) 854 gen.addJumpIfOneOf(R0, setOf(0, 257, 65536), DROP_LABEL) 855 gen.addJumpIfNoneOf(R0, setOf(1, 2, 3), DROP_LABEL) 856 program = gen.generate().skipDataAndDebug() 857 assertContentEquals(byteArrayOf( 858 encodeInstruction(21, 1, 1), 47, 24, -16, 1, 2, 3, 4, 5, 6, 859 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 860 29, 30, 31, 32, 861 encodeInstruction(21, 1, 0), 47, 8, 14, 0, 0, 0, 0, 0, 0, 862 1, 1, 0, 1, 0, 0, 863 encodeInstruction(21, 1, 0), 47, 1, 9, 1, 2, 3 864 ), program) 865 866 gen = ApfV6Generator(defaultMaximumApfProgramSize) 867 gen.addJumpIfOneOf(R0, setOf(0, 128, 256, 65536), DROP_LABEL) 868 gen.addJumpIfNoneOf(R1, setOf(0, 128, 256, 65536), DROP_LABEL) 869 program = gen.generate().skipDataAndDebug() 870 assertContentEquals(listOf( 871 "0: joneof r0, DROP, { 0, 128, 256, 65536 }", 872 "20: jnoneof r1, DROP, { 0, 128, 256, 65536 }" 873 ), ApfJniUtils.disassembleApf(program).map{ it.trim() }) 874 875 gen = ApfV6Generator(defaultMaximumApfProgramSize) 876 gen.addJumpIfBytesAtR0EqualsAnyOf(listOf(byteArrayOf(1, 2), byteArrayOf(3, 4)), DROP_LABEL) 877 gen.addJumpIfBytesAtR0EqualNoneOf(listOf(byteArrayOf(1, 2), byteArrayOf(3, 4)), DROP_LABEL) 878 gen.addJumpIfBytesAtR0EqualNoneOf(listOf(byteArrayOf(1, 1), byteArrayOf(1, 1)), DROP_LABEL) 879 program = gen.generate().skipDataAndDebug() 880 assertContentEquals(byteArrayOf( 881 encodeInstruction(opcode = 20, immLength = 2, register = 1), 882 0, 15, 8, 2, 1, 2, 3, 4, 883 encodeInstruction(opcode = 20, immLength = 2, register = 0), 884 0, 6, 8, 2, 1, 2, 3, 4, 885 encodeInstruction(opcode = 20, immLength = 1, register = 0), 886 1, 2, 1, 1 887 ), program) 888 assertContentEquals(listOf( 889 "0: jbseq r0, 0x2, DROP, { 0102, 0304 }", 890 "9: jbsne r0, 0x2, DROP, { 0102, 0304 }", 891 "18: jbsne r0, 0x2, DROP, 0101" 892 ), ApfJniUtils.disassembleApf(program).map{ it.trim() }) 893 } 894 895 @Test testWriteToTxBuffernull896 fun testWriteToTxBuffer() { 897 var program = ApfV6Generator(defaultMaximumApfProgramSize) 898 .addAllocate(14) 899 .addWriteU8(0x01) 900 .addWriteU16(0x0203) 901 .addWriteU32(0x04050607) 902 .addWrite32(-2) 903 .addWrite32(byteArrayOf(0xff.toByte(), 0xfe.toByte(), 0xfd.toByte(), 0xfc.toByte())) 904 .addLoadImmediate(R0, 1) 905 .addWriteU8(R0) 906 .addLoadImmediate(R0, 0x0203) 907 .addWriteU16(R0) 908 .addLoadImmediate(R1, 0x04050607) 909 .addWriteU32(R1) 910 .addTransmitWithoutChecksum() 911 .generate() 912 assertPass(APF_VERSION_6, program, ByteArray(MIN_PKT_SIZE)) 913 assertContentEquals( 914 byteArrayOf( 915 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xff.toByte(), 916 0xff.toByte(), 0xff.toByte(), 0xfe.toByte(), 0xff.toByte(), 0xfe.toByte(), 917 0xfd.toByte(), 0xfc.toByte(), 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07), 918 ApfJniUtils.getTransmittedPacket() 919 ) 920 } 921 922 @Test testCopyToTxBuffernull923 fun testCopyToTxBuffer() { 924 var program = ApfV6Generator(byteArrayOf(33, 34, 35), defaultMaximumApfProgramSize) 925 .addAllocate(14) 926 .addDataCopy(3, 2) // arg1=src, arg2=len 927 .addDataCopy(5, 1) // arg1=src, arg2=len 928 .addPacketCopy(0, 1) // arg1=src, arg2=len 929 .addPacketCopy(1, 3) // arg1=src, arg2=len 930 .addLoadImmediate(R0, 3) // data copy offset 931 .addDataCopyFromR0(2) // len 932 .addLoadImmediate(R0, 5) // data copy offset 933 .addLoadImmediate(R1, 1) // len 934 .addDataCopyFromR0LenR1() 935 .addLoadImmediate(R0, 0) // packet copy offset 936 .addPacketCopyFromR0(1) // len 937 .addLoadImmediate(R0, 1) // packet copy offset 938 .addLoadImmediate(R1, 3) // len 939 .addPacketCopyFromR0LenR1() 940 .addTransmitWithoutChecksum() 941 .generate() 942 assertPass(APF_VERSION_6, program, testPacket) 943 assertContentEquals( 944 byteArrayOf(33, 34, 35, 1, 2, 3, 4, 33, 34, 35, 1, 2, 3, 4), 945 ApfJniUtils.getTransmittedPacket() 946 ) 947 } 948 949 @Test testCopyContentToTxBuffernull950 fun testCopyContentToTxBuffer() { 951 val program = ApfV6Generator(defaultMaximumApfProgramSize) 952 .addAllocate(18) 953 .addDataCopy(HexDump.hexStringToByteArray("112233445566")) 954 .addDataCopy(HexDump.hexStringToByteArray("223344")) 955 .addDataCopy(HexDump.hexStringToByteArray("778899")) 956 .addDataCopy(HexDump.hexStringToByteArray("112233445566")) 957 .addTransmitWithoutChecksum() 958 .generate() 959 assertContentEquals(listOf( 960 "0: data 9, 112233445566778899", 961 "12: debugbuf size=1788", 962 "16: allocate 18", 963 "20: datacopy src=3, len=6", 964 "23: datacopy src=4, len=3", 965 "26: datacopy src=9, len=3", 966 "29: datacopy src=3, len=6", 967 "32: transmit ip_ofs=255" 968 ), ApfJniUtils.disassembleApf(program).map{ it.trim() }) 969 assertPass(APF_VERSION_6, program, testPacket) 970 val transmitPkt = HexDump.toHexString(ApfJniUtils.getTransmittedPacket()) 971 assertEquals("112233445566223344778899112233445566", transmitPkt) 972 } 973 974 @Test testPassDropnull975 fun testPassDrop() { 976 var program = ApfV6Generator(defaultMaximumApfProgramSize) 977 .addDrop() 978 .addPass() 979 .generate() 980 assertDrop(APF_VERSION_6, program, testPacket) 981 982 program = ApfV6Generator(defaultMaximumApfProgramSize) 983 .addCountAndDrop(Counter.DROPPED_ETH_BROADCAST) 984 .generate() 985 verifyProgramRun(APF_VERSION_6, program, testPacket, DROPPED_ETH_BROADCAST) 986 987 program = ApfV6Generator(defaultMaximumApfProgramSize) 988 .addCountAndPass(Counter.PASSED_ARP) 989 .generate() 990 verifyProgramRun(APF_VERSION_6, program, testPacket, PASSED_ARP) 991 } 992 993 @Test testLoadStoreCounternull994 fun testLoadStoreCounter() { 995 doTestLoadStoreCounter ( 996 { mutableMapOf() }, 997 { ApfV4Generator(APF_VERSION_3) } 998 ) 999 doTestLoadStoreCounter ( 1000 { mutableMapOf(TOTAL_PACKETS to 1) }, 1001 { ApfV6Generator(defaultMaximumApfProgramSize) } 1002 ) 1003 } 1004 doTestLoadStoreCounternull1005 private fun doTestLoadStoreCounter( 1006 getInitialMap: () -> MutableMap<Counter, Long>, 1007 getGenerator: () -> ApfV4GeneratorBase<*> 1008 ) { 1009 val program = getGenerator() 1010 .addIncrementCounter(PASSED_ARP, 2) 1011 .addPass() 1012 .generate() 1013 var dataRegion = ByteArray(Counter.totalSize()) { 0 } 1014 assertVerdict(APF_VERSION_6, PASS, program, testPacket, dataRegion) 1015 var counterMap = decodeCountersIntoMap(dataRegion) 1016 var expectedMap = getInitialMap() 1017 expectedMap[PASSED_ARP] = 2 1018 assertEquals(expectedMap, counterMap) 1019 } 1020 1021 @Test testV4CountAndPassDropCompareR0null1022 fun testV4CountAndPassDropCompareR0() { 1023 doTestCountAndPassDropCompareR0( 1024 getGenerator = { ApfV4Generator(APF_VERSION_3) }, 1025 incTotal = false 1026 ) 1027 } 1028 1029 @Test testV6CountAndPassDropCompareR0null1030 fun testV6CountAndPassDropCompareR0() { 1031 doTestCountAndPassDropCompareR0( 1032 getGenerator = { ApfV6Generator(defaultMaximumApfProgramSize) }, 1033 incTotal = true 1034 ) 1035 } 1036 doTestCountAndPassDropCompareR0null1037 private fun doTestCountAndPassDropCompareR0( 1038 getGenerator: () -> ApfV4GeneratorBase<*>, 1039 incTotal: Boolean 1040 ) { 1041 var program = getGenerator() 1042 .addLoadImmediate(R0, 123) 1043 .addCountAndDropIfR0Equals(123, Counter.DROPPED_ETH_BROADCAST) 1044 .addPass() 1045 .addCountTrampoline() 1046 .generate() 1047 verifyProgramRun( 1048 APF_VERSION_6, 1049 program, 1050 testPacket, 1051 DROPPED_ETH_BROADCAST, 1052 incTotal = incTotal 1053 ) 1054 1055 program = getGenerator() 1056 .addLoadImmediate(R0, 123) 1057 .addCountAndPassIfR0Equals(123, Counter.PASSED_ARP) 1058 .addPass() 1059 .addCountTrampoline() 1060 .generate() 1061 verifyProgramRun(APF_VERSION_6, program, testPacket, PASSED_ARP, incTotal = incTotal) 1062 1063 program = getGenerator() 1064 .addLoadImmediate(R0, 123) 1065 .addCountAndDropIfR0NotEquals(124, Counter.DROPPED_ETH_BROADCAST) 1066 .addPass() 1067 .addCountTrampoline() 1068 .generate() 1069 verifyProgramRun( 1070 APF_VERSION_6, 1071 program, 1072 testPacket, 1073 DROPPED_ETH_BROADCAST, 1074 incTotal = incTotal 1075 ) 1076 1077 program = getGenerator() 1078 .addLoadImmediate(R0, 123) 1079 .addCountAndPassIfR0NotEquals(124, Counter.PASSED_ARP) 1080 .addPass() 1081 .addCountTrampoline() 1082 .generate() 1083 verifyProgramRun(APF_VERSION_6, program, testPacket, PASSED_ARP, incTotal = incTotal) 1084 1085 program = getGenerator() 1086 .addLoadImmediate(R0, 123) 1087 .addCountAndDropIfR0LessThan(124, Counter.DROPPED_ETH_BROADCAST) 1088 .addPass() 1089 .addCountTrampoline() 1090 .generate() 1091 verifyProgramRun( 1092 APF_VERSION_6, 1093 program, 1094 testPacket, 1095 DROPPED_ETH_BROADCAST, 1096 incTotal = incTotal 1097 ) 1098 1099 program = getGenerator() 1100 .addLoadImmediate(R0, 123) 1101 .addCountAndPassIfR0LessThan(124, Counter.PASSED_ARP) 1102 .addPass() 1103 .addCountTrampoline() 1104 .generate() 1105 verifyProgramRun(APF_VERSION_6, program, testPacket, PASSED_ARP, incTotal = incTotal) 1106 1107 program = getGenerator() 1108 .addLoadImmediate(R0, 123) 1109 .addCountAndDropIfR0GreaterThan(122, Counter.DROPPED_ETH_BROADCAST) 1110 .addPass() 1111 .addCountTrampoline() 1112 .generate() 1113 verifyProgramRun( 1114 APF_VERSION_6, 1115 program, 1116 testPacket, 1117 DROPPED_ETH_BROADCAST, 1118 incTotal = incTotal 1119 ) 1120 1121 program = getGenerator() 1122 .addLoadImmediate(R0, 123) 1123 .addCountAndPassIfR0GreaterThan(122, Counter.PASSED_ARP) 1124 .addPass() 1125 .addCountTrampoline() 1126 .generate() 1127 verifyProgramRun(APF_VERSION_6, program, testPacket, PASSED_ARP, incTotal = incTotal) 1128 1129 program = getGenerator() 1130 .addLoadImmediate(R0, 1) 1131 .addCountAndDropIfBytesAtR0NotEqual( 1132 byteArrayOf(5, 5), DROPPED_ETH_BROADCAST) 1133 .addPass() 1134 .addCountTrampoline() 1135 .generate() 1136 verifyProgramRun( 1137 APF_VERSION_6, 1138 program, 1139 testPacket, 1140 DROPPED_ETH_BROADCAST, 1141 incTotal = incTotal 1142 ) 1143 1144 program = getGenerator() 1145 .addLoadImmediate(R0, 1) 1146 .addCountAndPassIfBytesAtR0NotEqual( 1147 byteArrayOf(5, 5), PASSED_ARP) 1148 .addPass() 1149 .addCountTrampoline() 1150 .generate() 1151 verifyProgramRun(APF_VERSION_6, program, testPacket, PASSED_ARP, incTotal = incTotal) 1152 1153 program = getGenerator() 1154 .addLoadImmediate(R0, 1) 1155 .addCountAndDropIfR0AnyBitsSet(0xffff, DROPPED_ETH_BROADCAST) 1156 .addPass() 1157 .addCountTrampoline() 1158 .generate() 1159 verifyProgramRun( 1160 APF_VERSION_6, 1161 program, 1162 testPacket, 1163 DROPPED_ETH_BROADCAST, 1164 incTotal = incTotal 1165 ) 1166 1167 program = getGenerator() 1168 .addLoadImmediate(R0, 1) 1169 .addCountAndPassIfR0AnyBitsSet(0xffff, PASSED_ARP) 1170 .addPass() 1171 .addCountTrampoline() 1172 .generate() 1173 verifyProgramRun(APF_VERSION_6, program, testPacket, PASSED_ARP, incTotal = incTotal) 1174 1175 program = getGenerator() 1176 .addLoadImmediate(R0, 123) 1177 .addCountAndDropIfR0IsOneOf(setOf(123), DROPPED_ETH_BROADCAST) 1178 .addPass() 1179 .addCountTrampoline() 1180 .generate() 1181 verifyProgramRun( 1182 APF_VERSION_6, 1183 program, 1184 testPacket, 1185 DROPPED_ETH_BROADCAST, 1186 incTotal = incTotal 1187 ) 1188 1189 program = getGenerator() 1190 .addLoadImmediate(R0, 123) 1191 .addCountAndPassIfR0IsOneOf(setOf(123), PASSED_ARP) 1192 .addPass() 1193 .addCountTrampoline() 1194 .generate() 1195 verifyProgramRun(APF_VERSION_6, program, testPacket, PASSED_ARP, incTotal = incTotal) 1196 1197 program = getGenerator() 1198 .addLoadImmediate(R0, 123) 1199 .addCountAndDropIfR0IsNoneOf(setOf(124), DROPPED_ETH_BROADCAST) 1200 .addPass() 1201 .addCountTrampoline() 1202 .generate() 1203 verifyProgramRun( 1204 APF_VERSION_6, 1205 program, 1206 testPacket, 1207 DROPPED_ETH_BROADCAST, 1208 incTotal = incTotal 1209 ) 1210 1211 program = getGenerator() 1212 .addLoadImmediate(R0, 123) 1213 .addCountAndPassIfR0IsNoneOf(setOf(124), PASSED_ARP) 1214 .addPass() 1215 .addCountTrampoline() 1216 .generate() 1217 verifyProgramRun(APF_VERSION_6, program, testPacket, PASSED_ARP, incTotal = incTotal) 1218 1219 program = getGenerator() 1220 .addLoadImmediate(R0, 123) 1221 .addCountAndDropIfR0IsOneOf(setOf(123, 124), DROPPED_ETH_BROADCAST) 1222 .addPass() 1223 .addCountTrampoline() 1224 .generate() 1225 verifyProgramRun( 1226 APF_VERSION_6, 1227 program, 1228 testPacket, 1229 DROPPED_ETH_BROADCAST, 1230 incTotal = incTotal 1231 ) 1232 1233 program = getGenerator() 1234 .addLoadImmediate(R0, 123) 1235 .addCountAndPassIfR0IsOneOf(setOf(123, 124), PASSED_ARP) 1236 .addPass() 1237 .addCountTrampoline() 1238 .generate() 1239 verifyProgramRun(APF_VERSION_6, program, testPacket, PASSED_ARP, incTotal = incTotal) 1240 1241 program = getGenerator() 1242 .addLoadImmediate(R0, 123) 1243 .addCountAndDropIfR0IsNoneOf(setOf(122, 124), DROPPED_ETH_BROADCAST) 1244 .addPass() 1245 .addCountTrampoline() 1246 .generate() 1247 verifyProgramRun( 1248 APF_VERSION_6, 1249 program, 1250 testPacket, 1251 DROPPED_ETH_BROADCAST, 1252 incTotal = incTotal 1253 ) 1254 1255 program = getGenerator() 1256 .addLoadImmediate(R0, 123) 1257 .addCountAndPassIfR0IsNoneOf(setOf(122, 124), PASSED_ARP) 1258 .addPass() 1259 .addCountTrampoline() 1260 .generate() 1261 verifyProgramRun(APF_VERSION_6, program, testPacket, PASSED_ARP, incTotal = incTotal) 1262 1263 program = getGenerator() 1264 .addLoadImmediate(R0, 0) 1265 .addCountAndDropIfBytesAtR0EqualsAnyOf( 1266 listOf(byteArrayOf(1, 2), byteArrayOf(3, 4)), 1267 DROPPED_ETH_BROADCAST 1268 ) 1269 .addPass() 1270 .addCountTrampoline() 1271 .generate() 1272 verifyProgramRun( 1273 APF_VERSION_6, 1274 program, 1275 testPacket, 1276 DROPPED_ETH_BROADCAST, 1277 incTotal = incTotal 1278 ) 1279 1280 program = getGenerator() 1281 .addLoadImmediate(R0, 0) 1282 .addCountAndPassIfBytesAtR0EqualsAnyOf( 1283 listOf(byteArrayOf(1, 2), byteArrayOf(3, 4)), 1284 PASSED_ARP 1285 ) 1286 .addPass() 1287 .addCountTrampoline() 1288 .generate() 1289 verifyProgramRun(APF_VERSION_6, program, testPacket, PASSED_ARP, incTotal = incTotal) 1290 1291 program = getGenerator() 1292 .addLoadImmediate(R0, 0) 1293 .addCountAndDropIfBytesAtR0EqualsNoneOf( 1294 listOf(byteArrayOf(1, 3), byteArrayOf(3, 4)), 1295 DROPPED_ETH_BROADCAST 1296 ) 1297 .addPass() 1298 .addCountTrampoline() 1299 .generate() 1300 verifyProgramRun( 1301 APF_VERSION_6, 1302 program, 1303 testPacket, 1304 DROPPED_ETH_BROADCAST, 1305 incTotal = incTotal 1306 ) 1307 1308 program = getGenerator() 1309 .addLoadImmediate(R0, 0) 1310 .addCountAndPassIfBytesAtR0EqualsNoneOf( 1311 listOf(byteArrayOf(1, 3), byteArrayOf(3, 4)), 1312 PASSED_ARP 1313 ) 1314 .addPass() 1315 .addCountTrampoline() 1316 .generate() 1317 verifyProgramRun(APF_VERSION_6, program, testPacket, PASSED_ARP, incTotal = incTotal) 1318 1319 program = getGenerator() 1320 .addLoadImmediate(R0, 1) 1321 .addCountAndDropIfBytesAtR0Equal( 1322 byteArrayOf(2, 3), DROPPED_ETH_BROADCAST) 1323 .addPass() 1324 .addCountTrampoline() 1325 .generate() 1326 verifyProgramRun( 1327 APF_VERSION_6, 1328 program, 1329 testPacket, 1330 DROPPED_ETH_BROADCAST, 1331 incTotal = incTotal 1332 ) 1333 1334 program = getGenerator() 1335 .addLoadImmediate(R0, 1) 1336 .addCountAndPassIfBytesAtR0Equal( 1337 byteArrayOf(2, 3), PASSED_ARP) 1338 .addPass() 1339 .addCountTrampoline() 1340 .generate() 1341 verifyProgramRun(APF_VERSION_6, program, testPacket, PASSED_ARP, incTotal = incTotal) 1342 } 1343 doTestEtherTypeAllowListFilternull1344 private fun doTestEtherTypeAllowListFilter(apfVersion: Int) { 1345 val programCaptor = ArgumentCaptor.forClass(ByteArray::class.java) 1346 val apfFilter = 1347 ApfFilter( 1348 context, 1349 getDefaultConfig(apfVersion), 1350 ifParams, 1351 ipClientCallback, 1352 metrics, 1353 dependencies 1354 ) 1355 verify(ipClientCallback, times(2)).installPacketFilter(programCaptor.capture()) 1356 val program = programCaptor.allValues.last() 1357 1358 // Using scapy to generate IPv4 mDNS packet: 1359 // eth = Ether(src="E8:9F:80:66:60:BB", dst="01:00:5E:00:00:FB") 1360 // ip = IP(src="192.168.1.1") 1361 // udp = UDP(sport=5353, dport=5353) 1362 // dns = DNS(qd=DNSQR(qtype="PTR", qname="a.local")) 1363 // p = eth/ip/udp/dns 1364 val mdnsPkt = "01005e0000fbe89f806660bb080045000035000100004011d812c0a80101e00000f" + 1365 "b14e914e900214d970000010000010000000000000161056c6f63616c00000c0001" 1366 verifyProgramRun(APF_VERSION_6, program, HexDump.hexStringToByteArray(mdnsPkt), PASSED_IPV4) 1367 1368 // Using scapy to generate RA packet: 1369 // eth = Ether(src="E8:9F:80:66:60:BB", dst="33:33:00:00:00:01") 1370 // ip6 = IPv6(src="fe80::1", dst="ff02::1") 1371 // icmp6 = ICMPv6ND_RA(routerlifetime=3600, retranstimer=3600) 1372 // p = eth/ip6/icmp6 1373 val raPkt = "333300000001e89f806660bb86dd6000000000103afffe800000000000000000000000" + 1374 "000001ff0200000000000000000000000000018600600700080e100000000000000e10" 1375 verifyProgramRun( 1376 APF_VERSION_6, 1377 program, 1378 HexDump.hexStringToByteArray(raPkt), 1379 PASSED_IPV6_ICMP 1380 ) 1381 1382 // Using scapy to generate ethernet packet with type 0x88A2: 1383 // p = Ether(type=0x88A2)/Raw(load="01") 1384 val ethPkt = "ffffffffffff047bcb463fb588a23031" 1385 verifyProgramRun( 1386 APF_VERSION_6, 1387 program, 1388 HexDump.hexStringToByteArray(ethPkt), 1389 DROPPED_ETHERTYPE_NOT_ALLOWED 1390 ) 1391 1392 apfFilter.shutdown() 1393 } 1394 1395 @Test 1396 @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) testV4EtherTypeAllowListFilternull1397 fun testV4EtherTypeAllowListFilter() { 1398 doTestEtherTypeAllowListFilter(APF_VERSION_3) 1399 } 1400 1401 @Test 1402 @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) testV6EtherTypeAllowListFilternull1403 fun testV6EtherTypeAllowListFilter() { 1404 doTestEtherTypeAllowListFilter(APF_VERSION_6) 1405 } 1406 1407 @Test testV4CountAndPassDropnull1408 fun testV4CountAndPassDrop() { 1409 var program = ApfV4Generator(APF_VERSION_3) 1410 .addCountAndDrop(Counter.DROPPED_ETH_BROADCAST) 1411 .addCountTrampoline() 1412 .generate() 1413 verifyProgramRun( 1414 APF_VERSION_6, 1415 program, 1416 testPacket, 1417 DROPPED_ETH_BROADCAST, 1418 incTotal = false 1419 ) 1420 1421 program = ApfV4Generator(APF_VERSION_3) 1422 .addCountAndPass(Counter.PASSED_ARP) 1423 .addCountTrampoline() 1424 .generate() 1425 verifyProgramRun(APF_VERSION_6, program, testPacket, PASSED_ARP, incTotal = false) 1426 } 1427 1428 @Test testV2CountAndPassDropnull1429 fun testV2CountAndPassDrop() { 1430 var program = ApfV4Generator(APF_VERSION_2) 1431 .addCountAndDrop(Counter.DROPPED_ETH_BROADCAST) 1432 .addCountTrampoline() 1433 .generate() 1434 var dataRegion = ByteArray(Counter.totalSize()) { 0 } 1435 assertVerdict(APF_VERSION_6, DROP, program, testPacket, dataRegion) 1436 assertContentEquals(ByteArray(Counter.totalSize()) { 0 }, dataRegion) 1437 1438 program = ApfV4Generator(APF_VERSION_2) 1439 .addCountAndPass(PASSED_ARP) 1440 .addCountTrampoline() 1441 .generate() 1442 dataRegion = ByteArray(Counter.totalSize()) { 0 } 1443 assertVerdict(APF_VERSION_6, PASS, program, testPacket, dataRegion) 1444 assertContentEquals(ByteArray(Counter.totalSize()) { 0 }, dataRegion) 1445 } 1446 1447 @Test testAllocateFailurenull1448 fun testAllocateFailure() { 1449 val program = ApfV6Generator(defaultMaximumApfProgramSize) 1450 // allocate size: 65535 > sizeof(apf_test_buffer): 1514, trigger allocate failure. 1451 .addAllocate(65535) 1452 .addDrop() 1453 .generate() 1454 verifyProgramRun(APF_VERSION_6, program, testPacket, PASSED_ALLOCATE_FAILURE) 1455 } 1456 1457 @Test testTransmitFailurenull1458 fun testTransmitFailure() { 1459 val program = ApfV6Generator(defaultMaximumApfProgramSize) 1460 .addAllocate(14) 1461 // len: 13 is less than ETH_HLEN, trigger transmit failure. 1462 .addLoadImmediate(R0, 13) 1463 .addStoreToMemory(MemorySlot.TX_BUFFER_OUTPUT_POINTER, R0) 1464 .addTransmitWithoutChecksum() 1465 .addDrop() 1466 .generate() 1467 verifyProgramRun(APF_VERSION_6, program, testPacket, PASSED_TRANSMIT_FAILURE) 1468 } 1469 1470 @Test testTransmitL4null1471 fun testTransmitL4() { 1472 val etherIpv4UdpPacket = intArrayOf( 1473 0x01, 0x00, 0x5e, 0x00, 0x00, 0xfb, 1474 0x38, 0xca, 0x84, 0xb7, 0x7f, 0x16, 1475 0x08, 0x00, // end of ethernet header 1476 0x45, 1477 0x04, 1478 0x00, 0x3f, 1479 0x43, 0xcd, 1480 0x40, 0x00, 1481 0xff, 1482 0x11, 1483 0x00, 0x00, // ipv4 checksum set to 0 1484 0xc0, 0xa8, 0x01, 0x03, 1485 0xe0, 0x00, 0x00, 0xfb, // end of ipv4 header 1486 0x14, 0xe9, 1487 0x14, 0xe9, 1488 0x00, 0x2b, 1489 0x00, 0x2b, // end of udp header. udp checksum set to udp (header + payload) size 1490 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 1491 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x62, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 1492 0x00, 0x00, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x04, 0xc0, 0xa8, 0x01, 1493 0x09, 1494 ).map { it.toByte() }.toByteArray() 1495 val program = ApfV6Generator(etherIpv4UdpPacket, defaultMaximumApfProgramSize) 1496 .addAllocate(etherIpv4UdpPacket.size) 1497 .addDataCopy(3, etherIpv4UdpPacket.size) // arg1=src, arg2=len 1498 .addTransmitL4( 1499 ETH_HLEN, // ipOfs, 1500 ETH_HLEN + IPV4_HLEN + 6, // csumOfs 1501 ETH_HLEN + IPV4_HLEN - 8, // csumStart 1502 IPPROTO_UDP, // partialCsum 1503 true // isUdp 1504 ) 1505 .generate() 1506 assertPass(APF_VERSION_6, program, testPacket) 1507 val txBuf = ByteBuffer.wrap(ApfJniUtils.getTransmittedPacket()) 1508 Struct.parse(EthernetHeader::class.java, txBuf) 1509 val ipv4Hdr = Struct.parse(Ipv4Header::class.java, txBuf) 1510 val udpHdr = Struct.parse(UdpHeader::class.java, txBuf) 1511 assertEquals(0x9535.toShort(), ipv4Hdr.checksum) 1512 assertEquals(0xa73d.toShort(), udpHdr.checksum) 1513 } 1514 1515 @Test testDnsQuestionMatchnull1516 fun testDnsQuestionMatch() { 1517 // needles = { A, B.LOCAL } 1518 val needlesMatch = intArrayOf( 1519 0x01, 'A'.code, 1520 0x00, 1521 0x01, 'B'.code, 1522 0x05, 'L'.code, 'O'.code, 'C'.code, 'A'.code, 'L'.code, 1523 0x00, 1524 0x00 1525 ).map { it.toByte() }.toByteArray() 1526 val udpPayload = intArrayOf( 1527 0x00, 0x00, 0x00, 0x00, // tid = 0x00, flags = 0x00, 1528 0x00, 0x02, // qdcount = 2 1529 0x00, 0x00, // ancount = 0 1530 0x00, 0x00, // nscount = 0 1531 0x00, 0x00, // arcount = 0 1532 0x01, 'a'.code, 1533 0x01, 'b'.code, 1534 0x05, 'l'.code, 'o'.code, 'c'.code, 'a'.code, 'l'.code, 1535 0x00, // qname1 = a.b.local 1536 0x00, 0x01, 0x00, 0x01, // type = A, class = 0x0001 1537 0xc0, 0x0e, // qname2 = b.local (name compression) 1538 0x00, 0x01, 0x00, 0x01 // type = A, class = 0x0001 1539 ).map { it.toByte() }.toByteArray() 1540 1541 var program = ApfV6Generator(defaultMaximumApfProgramSize) 1542 .addLoadImmediate(R0, 0) 1543 .addJumpIfPktAtR0ContainDnsQ(needlesMatch, 0x01, DROP_LABEL) // arg2=qtype 1544 .addPass() 1545 .generate() 1546 assertDrop(APF_VERSION_6, program, udpPayload) 1547 1548 program = ApfV6Generator(defaultMaximumApfProgramSize) 1549 .addLoadImmediate(R0, 0) 1550 .addJumpIfPktAtR0ContainDnsQSafe(needlesMatch, 0x01, DROP_LABEL) 1551 .addPass() 1552 .generate() 1553 assertDrop(APF_VERSION_6, program, udpPayload) 1554 1555 program = ApfV6Generator(defaultMaximumApfProgramSize) 1556 .addLoadImmediate(R0, 0) 1557 .addJumpIfPktAtR0DoesNotContainDnsQ(needlesMatch, 0x01, DROP_LABEL) // arg2=qtype 1558 .addPass() 1559 .generate() 1560 assertPass(APF_VERSION_6, program, udpPayload) 1561 1562 program = ApfV6Generator(defaultMaximumApfProgramSize) 1563 .addLoadImmediate(R0, 0) 1564 .addJumpIfPktAtR0DoesNotContainDnsQSafe(needlesMatch, 0x01, DROP_LABEL) // arg2=qtype 1565 .addPass() 1566 .generate() 1567 assertPass(APF_VERSION_6, program, udpPayload) 1568 1569 val badUdpPayload = intArrayOf( 1570 0x00, 0x00, 0x00, 0x00, // tid = 0x00, flags = 0x00, 1571 0x00, 0x02, // qdcount = 2 1572 0x00, 0x00, // ancount = 0 1573 0x00, 0x00, // nscount = 0 1574 0x00, 0x00, // arcount = 0 1575 0x01, 'a'.code, 1576 0x01, 'b'.code, 1577 0x05, 'l'.code, 'o'.code, 'c'.code, 'a'.code, 'l'.code, 1578 0x00, // qname1 = a.b.local 1579 0x00, 0x01, 0x00, 0x01, // type = A, class = 0x0001 1580 0xc0, 0x1b, // corrupted pointer cause infinite loop 1581 0x00, 0x01, 0x00, 0x01 // type = A, class = 0x0001 1582 ).map { it.toByte() }.toByteArray() 1583 1584 program = ApfV6Generator(defaultMaximumApfProgramSize) 1585 .addLoadImmediate(R0, 0) 1586 .addJumpIfPktAtR0ContainDnsQ(needlesMatch, 0x01, DROP_LABEL) // arg2=qtype 1587 .addPass() 1588 .generate() 1589 verifyProgramRun(APF_VERSION_6, program, badUdpPayload, CORRUPT_DNS_PACKET, result = DROP) 1590 1591 program = ApfV6Generator(defaultMaximumApfProgramSize) 1592 .addLoadImmediate(R0, 0) 1593 .addJumpIfPktAtR0ContainDnsQSafe(needlesMatch, 0x01, DROP_LABEL) // arg2=qtype 1594 .addPass() 1595 .generate() 1596 verifyProgramRun(APF_VERSION_6, program, badUdpPayload, CORRUPT_DNS_PACKET, result = PASS) 1597 } 1598 1599 @Test testDnsAnswerMatchnull1600 fun testDnsAnswerMatch() { 1601 // needles = { A, B.LOCAL } 1602 val needlesMatch = intArrayOf( 1603 0x01, 'A'.code, 1604 0x00, 1605 0x01, 'B'.code, 1606 0x05, 'L'.code, 'O'.code, 'C'.code, 'A'.code, 'L'.code, 1607 0x00, 1608 0x00 1609 ).map { it.toByte() }.toByteArray() 1610 1611 val udpPayload = intArrayOf( 1612 0x00, 0x00, 0x84, 0x00, // tid = 0x00, flags = 0x8400, 1613 0x00, 0x00, // qdcount = 0 1614 0x00, 0x02, // ancount = 2 1615 0x00, 0x00, // nscount = 0 1616 0x00, 0x00, // arcount = 0 1617 0x01, 'a'.code, 1618 0x01, 'b'.code, 1619 0x05, 'l'.code, 'o'.code, 'c'.code, 'a'.code, 'l'.code, 1620 0x00, // name1 = a.b.local 1621 0x00, 0x01, 0x80, 0x01, // type = A, class = 0x8001 1622 0x00, 0x00, 0x00, 0x78, // ttl = 120 1623 0x00, 0x04, 0xc0, 0xa8, 0x01, 0x09, // rdlengh = 4, rdata = 192.168.1.9 1624 0xc0, 0x0e, // name2 = b.local (name compression) 1625 0x00, 0x01, 0x80, 0x01, // type = A, class = 0x8001 1626 0x00, 0x00, 0x00, 0x78, // ttl = 120 1627 0x00, 0x04, 0xc0, 0xa8, 0x01, 0x09 // rdlengh = 4, rdata = 192.168.1.9 1628 ).map { it.toByte() }.toByteArray() 1629 1630 var program = ApfV6Generator(defaultMaximumApfProgramSize) 1631 .addLoadImmediate(R0, 0) 1632 .addJumpIfPktAtR0ContainDnsA(needlesMatch, DROP_LABEL) 1633 .addPass() 1634 .generate() 1635 assertDrop(APF_VERSION_6, program, udpPayload) 1636 1637 program = ApfV6Generator(defaultMaximumApfProgramSize) 1638 .addLoadImmediate(R0, 0) 1639 .addJumpIfPktAtR0ContainDnsASafe(needlesMatch, DROP_LABEL) 1640 .addPass() 1641 .generate() 1642 assertDrop(APF_VERSION_6, program, udpPayload) 1643 1644 program = ApfV6Generator(defaultMaximumApfProgramSize) 1645 .addLoadImmediate(R0, 0) 1646 .addJumpIfPktAtR0DoesNotContainDnsA(needlesMatch, DROP_LABEL) 1647 .addPass() 1648 .generate() 1649 assertPass(APF_VERSION_6, program, udpPayload) 1650 1651 program = ApfV6Generator(defaultMaximumApfProgramSize) 1652 .addLoadImmediate(R0, 0) 1653 .addJumpIfPktAtR0DoesNotContainDnsASafe(needlesMatch, DROP_LABEL) 1654 .addPass() 1655 .generate() 1656 assertPass(APF_VERSION_6, program, udpPayload) 1657 1658 val badUdpPayload = intArrayOf( 1659 0x00, 0x00, 0x84, 0x00, // tid = 0x00, flags = 0x8400, 1660 0x00, 0x00, // qdcount = 0 1661 0x00, 0x02, // ancount = 2 1662 0x00, 0x00, // nscount = 0 1663 0x00, 0x00, // arcount = 0 1664 0x01, 'a'.code, 1665 0x01, 'b'.code, 1666 0x05, 'l'.code, 'o'.code, 'c'.code, 'a'.code, 'l'.code, 1667 0x00, // name1 = a.b.local 1668 0x00, 0x01, 0x80, 0x01, // type = A, class = 0x8001 1669 0x00, 0x00, 0x00, 0x78, // ttl = 120 1670 0x00, 0x04, 0xc0, 0xa8, 0x01, 0x09, // rdlengh = 4, rdata = 192.168.1.9 1671 0xc0, 0x25, // corrupted pointer cause infinite loop 1672 0x00, 0x01, 0x80, 0x01, // type = A, class = 0x8001 1673 0x00, 0x00, 0x00, 0x78, // ttl = 120 1674 0x00, 0x04, 0xc0, 0xa8, 0x01, 0x09 // rdlengh = 4, rdata = 192.168.1.9 1675 ).map { it.toByte() }.toByteArray() 1676 1677 program = ApfV6Generator(defaultMaximumApfProgramSize) 1678 .addLoadImmediate(R0, 0) 1679 .addJumpIfPktAtR0ContainDnsA(needlesMatch, DROP_LABEL) 1680 .addPass() 1681 .generate() 1682 verifyProgramRun(APF_VERSION_6, program, badUdpPayload, CORRUPT_DNS_PACKET, result = DROP) 1683 1684 program = ApfV6Generator(defaultMaximumApfProgramSize) 1685 .addLoadImmediate(R0, 0) 1686 .addJumpIfPktAtR0ContainDnsASafe(needlesMatch, DROP_LABEL) 1687 .addPass() 1688 .generate() 1689 verifyProgramRun(APF_VERSION_6, program, badUdpPayload, CORRUPT_DNS_PACKET, result = PASS) 1690 } 1691 1692 @Test testGetCounterValuenull1693 fun testGetCounterValue() { 1694 val counterBytes = intArrayOf(0xff, 0, 0, 0, 0x78, 0x56, 0x34, 0x12) 1695 .map { it.toByte() }.toByteArray() 1696 assertEquals(0xff, ApfCounterTracker.getCounterValue(counterBytes, Counter.TOTAL_PACKETS)) 1697 } 1698 1699 @Test testJumpMultipleByteSequencesMatchnull1700 fun testJumpMultipleByteSequencesMatch() { 1701 var program = ApfV6Generator(defaultMaximumApfProgramSize) 1702 .addLoadImmediate(R0, 0) 1703 .addJumpIfBytesAtR0EqualsAnyOf( 1704 listOf(byteArrayOf(1, 2, 3), byteArrayOf(6, 5, 4)), 1705 DROP_LABEL 1706 ) 1707 .addPass() 1708 .generate() 1709 assertDrop(APF_VERSION_6, program, testPacket) 1710 1711 program = ApfV6Generator(defaultMaximumApfProgramSize) 1712 .addLoadImmediate(R0, 2) 1713 .addJumpIfBytesAtR0EqualsAnyOf( 1714 listOf(byteArrayOf(1, 2, 3), byteArrayOf(6, 5, 4)), 1715 DROP_LABEL 1716 ) 1717 .addPass() 1718 .generate() 1719 assertPass(APF_VERSION_6, program, testPacket) 1720 1721 program = ApfV6Generator(defaultMaximumApfProgramSize) 1722 .addLoadImmediate(R0, 1) 1723 .addJumpIfBytesAtR0EqualNoneOf( 1724 listOf(byteArrayOf(1, 2, 3), byteArrayOf(6, 5, 4)), 1725 DROP_LABEL 1726 ) 1727 .addPass() 1728 .generate() 1729 assertDrop(APF_VERSION_6, program, testPacket) 1730 1731 program = ApfV6Generator(defaultMaximumApfProgramSize) 1732 .addLoadImmediate(R0, 0) 1733 .addJumpIfBytesAtR0EqualNoneOf( 1734 listOf(byteArrayOf(1, 2, 3), byteArrayOf(6, 5, 4)), 1735 DROP_LABEL 1736 ) 1737 .addPass() 1738 .generate() 1739 assertPass(APF_VERSION_6, program, testPacket) 1740 } 1741 1742 @Test testJumpOneOfnull1743 fun testJumpOneOf() { 1744 var program = ApfV6Generator(defaultMaximumApfProgramSize) 1745 .addLoadImmediate(R0, 255) 1746 .addJumpIfOneOf(R0, setOf(1, 2, 3, 128, 255), DROP_LABEL) 1747 .addPass() 1748 .generate() 1749 assertDrop(APF_VERSION_6, program, testPacket) 1750 1751 program = ApfV6Generator(defaultMaximumApfProgramSize) 1752 .addLoadImmediate(R0, 254) 1753 .addJumpIfOneOf(R0, setOf(1, 2, 3, 128, 255), DROP_LABEL) 1754 .addPass() 1755 .generate() 1756 assertPass(APF_VERSION_6, program, testPacket) 1757 1758 program = ApfV6Generator(defaultMaximumApfProgramSize) 1759 .addLoadImmediate(R0, 254) 1760 .addJumpIfNoneOf(R0, setOf(1, 2, 3, 128, 255), DROP_LABEL) 1761 .addPass() 1762 .generate() 1763 assertDrop(APF_VERSION_6, program, testPacket) 1764 1765 program = ApfV6Generator(defaultMaximumApfProgramSize) 1766 .addLoadImmediate(R0, 255) 1767 .addJumpIfNoneOf(R0, setOf(1, 2, 3, 128, 255), DROP_LABEL) 1768 .addPass() 1769 .generate() 1770 assertPass(APF_VERSION_6, program, testPacket) 1771 } 1772 1773 @Test testDebugBuffernull1774 fun testDebugBuffer() { 1775 val program = ApfV6Generator(defaultMaximumApfProgramSize) 1776 .addLoad8(R0, 255) 1777 .generate() 1778 val dataRegion = ByteArray(defaultMaximumApfProgramSize - program.size) { 0 } 1779 1780 assertVerdict(APF_VERSION_6, PASS, program, testPacket, dataRegion) 1781 // offset 3 in the data region should contain if the interpreter is APFv6 mode or not 1782 assertEquals(1, dataRegion[3]) 1783 } 1784 1785 @Test testIPv4PacketFilterOnV6OnlyNetworknull1786 fun testIPv4PacketFilterOnV6OnlyNetwork() { 1787 val apfFilter = 1788 ApfFilter( 1789 context, 1790 getDefaultConfig(), 1791 ifParams, 1792 ipClientCallback, 1793 metrics, 1794 dependencies 1795 ) 1796 apfFilter.updateClatInterfaceState(true) 1797 val programCaptor = ArgumentCaptor.forClass(ByteArray::class.java) 1798 verify(ipClientCallback, times(3)).installPacketFilter(programCaptor.capture()) 1799 val program = programCaptor.allValues.last() 1800 1801 // Using scapy to generate IPv4 mDNS packet: 1802 // eth = Ether(src="E8:9F:80:66:60:BB", dst="01:00:5E:00:00:FB") 1803 // ip = IP(src="192.168.1.1") 1804 // udp = UDP(sport=5353, dport=5353) 1805 // dns = DNS(qd=DNSQR(qtype="PTR", qname="a.local")) 1806 // p = eth/ip/udp/dns 1807 val mdnsPkt = "01005e0000fbe89f806660bb080045000035000100004011d812c0a80101e00000f" + 1808 "b14e914e900214d970000010000010000000000000161056c6f63616c00000c0001" 1809 verifyProgramRun( 1810 APF_VERSION_6, 1811 program, 1812 HexDump.hexStringToByteArray(mdnsPkt), 1813 DROPPED_IPV4_NON_DHCP4 1814 ) 1815 1816 // Using scapy to generate DHCP4 offer packet: 1817 // ether = Ether(src='00:11:22:33:44:55', dst='ff:ff:ff:ff:ff:ff') 1818 // ip = IP(src='192.168.1.1', dst='255.255.255.255') 1819 // udp = UDP(sport=67, dport=68) 1820 // bootp = BOOTP(op=2, 1821 // yiaddr='192.168.1.100', 1822 // siaddr='192.168.1.1', 1823 // chaddr=b'\x00\x11\x22\x33\x44\x55') 1824 // dhcp_options = [('message-type', 'offer'), 1825 // ('server_id', '192.168.1.1'), 1826 // ('subnet_mask', '255.255.255.0'), 1827 // ('router', '192.168.1.1'), 1828 // ('lease_time', 86400), 1829 // ('name_server', '8.8.8.8'), 1830 // 'end'] 1831 // dhcp = DHCP(options=dhcp_options) 1832 // dhcp_offer_packet = ether/ip/udp/bootp/dhcp 1833 val dhcp4Pkt = "ffffffffffff00112233445508004500012e000100004011b815c0a80101ffffffff0043" + 1834 "0044011a5ffc02010600000000000000000000000000c0a80164c0a80101000000000011" + 1835 "223344550000000000000000000000000000000000000000000000000000000000000000" + 1836 "000000000000000000000000000000000000000000000000000000000000000000000000" + 1837 "000000000000000000000000000000000000000000000000000000000000000000000000" + 1838 "000000000000000000000000000000000000000000000000000000000000000000000000" + 1839 "000000000000000000000000000000000000000000000000000000000000000000000000" + 1840 "0000000000000000000000000000000000000000000000000000638253633501023604c0" + 1841 "a801010104ffffff000304c0a80101330400015180060408080808ff" 1842 verifyProgramRun( 1843 APF_VERSION_6, 1844 program, 1845 HexDump.hexStringToByteArray(dhcp4Pkt), 1846 PASSED_IPV4_FROM_DHCPV4_SERVER 1847 ) 1848 1849 // Using scapy to generate DHCP4 offer packet: 1850 // eth = Ether(src="E8:9F:80:66:60:BB", dst="01:00:5E:00:00:FB") 1851 // ip = IP(src="192.168.1.10", dst="192.168.1.20") # IPv4 1852 // udp = UDP(sport=12345, dport=53) 1853 // dns = DNS(qd=DNSQR(qtype="PTR", qname="a.local")) 1854 // pkt = eth / ip / udp / dns 1855 // fragments = fragment(pkt, fragsize=30) 1856 // fragments[1] 1857 val fragmentedUdpPkt = "01005e0000fbe89f806660bb08004500001d000100034011f75dc0a8010ac0a8" + 1858 "01146f63616c00000c0001" 1859 verifyProgramRun( 1860 APF_VERSION_6, 1861 program, 1862 HexDump.hexStringToByteArray(fragmentedUdpPkt), 1863 DROPPED_IPV4_NON_DHCP4 1864 ) 1865 apfFilter.shutdown() 1866 } 1867 1868 // The APFv6 code path is only turned on in V+ 1869 @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 1870 @Test testArpTransmitnull1871 fun testArpTransmit() { 1872 val apfFilter = 1873 ApfFilter( 1874 context, 1875 getDefaultConfig(), 1876 ifParams, 1877 ipClientCallback, 1878 metrics, 1879 dependencies 1880 ) 1881 verify(ipClientCallback, times(2)).installPacketFilter(any()) 1882 val linkAddress = LinkAddress(InetAddress.getByAddress(hostIpv4Address), 24) 1883 val lp = LinkProperties() 1884 lp.addLinkAddress(linkAddress) 1885 apfFilter.setLinkProperties(lp) 1886 val programCaptor = ArgumentCaptor.forClass(ByteArray::class.java) 1887 verify(ipClientCallback, times(3)).installPacketFilter(programCaptor.capture()) 1888 val program = programCaptor.value 1889 val receivedArpPacketBuf = ArpPacket.buildArpPacket( 1890 arpBroadcastMacAddress, 1891 senderMacAddress, 1892 hostIpv4Address, 1893 HexDump.hexStringToByteArray("000000000000"), 1894 senderIpv4Address, 1895 ARP_REQUEST.toShort() 1896 ) 1897 val receivedArpPacket = ByteArray(ARP_ETHER_IPV4_LEN) 1898 receivedArpPacketBuf.get(receivedArpPacket) 1899 verifyProgramRun(APF_VERSION_6, program, receivedArpPacket, DROPPED_ARP_REQUEST_REPLIED) 1900 1901 val transmittedPacket = ApfJniUtils.getTransmittedPacket() 1902 val expectedArpReplyBuf = ArpPacket.buildArpPacket( 1903 senderMacAddress, 1904 apfFilter.mHardwareAddress, 1905 senderIpv4Address, 1906 senderMacAddress, 1907 hostIpv4Address, 1908 ARP_REPLY.toShort() 1909 ) 1910 val expectedArpReplyPacket = ByteArray(ARP_ETHER_IPV4_LEN) 1911 expectedArpReplyBuf.get(expectedArpReplyPacket) 1912 assertContentEquals( 1913 expectedArpReplyPacket + ByteArray(18) {0}, 1914 transmittedPacket 1915 ) 1916 apfFilter.shutdown() 1917 } 1918 1919 @Test testArpOffloadDisablednull1920 fun testArpOffloadDisabled() { 1921 val apfConfig = getDefaultConfig() 1922 apfConfig.shouldHandleArpOffload = false 1923 val apfFilter = 1924 ApfFilter( 1925 context, 1926 apfConfig, 1927 ifParams, 1928 ipClientCallback, 1929 metrics, 1930 dependencies 1931 ) 1932 verify(ipClientCallback, times(2)).installPacketFilter(any()) 1933 val linkAddress = LinkAddress(InetAddress.getByAddress(hostIpv4Address), 24) 1934 val lp = LinkProperties() 1935 lp.addLinkAddress(linkAddress) 1936 apfFilter.setLinkProperties(lp) 1937 val programCaptor = ArgumentCaptor.forClass(ByteArray::class.java) 1938 verify(ipClientCallback, times(3)).installPacketFilter(programCaptor.capture()) 1939 val program = programCaptor.value 1940 val receivedArpPacketBuf = ArpPacket.buildArpPacket( 1941 arpBroadcastMacAddress, 1942 senderMacAddress, 1943 hostIpv4Address, 1944 HexDump.hexStringToByteArray("000000000000"), 1945 senderIpv4Address, 1946 ARP_REQUEST.toShort() 1947 ) 1948 val receivedArpPacket = ByteArray(ARP_ETHER_IPV4_LEN) 1949 receivedArpPacketBuf.get(receivedArpPacket) 1950 verifyProgramRun(APF_VERSION_6, program, receivedArpPacket, PASSED_ARP_REQUEST) 1951 apfFilter.shutdown() 1952 } 1953 1954 @Test 1955 @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) testNsFilterNoIPv6null1956 fun testNsFilterNoIPv6() { 1957 `when`(dependencies.getAnycast6Addresses(any())).thenReturn(listOf()) 1958 val apfFilter = 1959 ApfFilter( 1960 context, 1961 getDefaultConfig(), 1962 ifParams, 1963 ipClientCallback, 1964 metrics, 1965 dependencies 1966 ) 1967 1968 // validate NS packet check when there is no IPv6 address 1969 val programCaptor = ArgumentCaptor.forClass(ByteArray::class.java) 1970 verify(ipClientCallback, times(2)).installPacketFilter(programCaptor.capture()) 1971 val program = programCaptor.allValues.last() 1972 // Using scapy to generate IPv6 NS packet: 1973 // eth = Ether(src="00:01:02:03:04:05", dst="01:02:03:04:05:06") 1974 // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255) 1975 // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") 1976 // pkt = eth/ip6/icmp6 1977 val nsPkt = "01020304050600010203040586DD6000000000183AFF200100000000000" + 1978 "00200001A1122334420010000000000000200001A334411228700452900" + 1979 "00000020010000000000000200001A33441122" 1980 // when there is no IPv6 addresses -> pass NS packet 1981 verifyProgramRun( 1982 APF_VERSION_6, 1983 program, 1984 HexDump.hexStringToByteArray(nsPkt), 1985 PASSED_IPV6_NS_NO_ADDRESS 1986 ) 1987 1988 apfFilter.shutdown() 1989 } 1990 1991 @Test 1992 @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) testNsFilternull1993 fun testNsFilter() { 1994 val apfFilter = 1995 ApfFilter( 1996 context, 1997 getDefaultConfig(), 1998 ifParams, 1999 ipClientCallback, 2000 metrics, 2001 dependencies 2002 ) 2003 verify(ipClientCallback, times(2)).installPacketFilter(any()) 2004 2005 // validate Ethernet dst address check 2006 2007 val lp = LinkProperties() 2008 for (addr in hostIpv6Addresses) { 2009 lp.addLinkAddress(LinkAddress(InetAddress.getByAddress(addr), 64)) 2010 } 2011 2012 apfFilter.setLinkProperties(lp) 2013 verify(ipClientCallback, times(3)).installPacketFilter(any()) 2014 apfFilter.updateClatInterfaceState(true) 2015 val programCaptor = ArgumentCaptor.forClass(ByteArray::class.java) 2016 verify(ipClientCallback, times(4)).installPacketFilter(programCaptor.capture()) 2017 val program = programCaptor.value 2018 2019 // Using scapy to generate IPv6 NS packet: 2020 // eth = Ether(src="00:01:02:03:04:05", dst="00:05:04:03:02:01") 2021 // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255) 2022 // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") 2023 // pkt = eth/ip6/icmp6 2024 val nonHostDstMacNsPkt = "00050403020100010203040586DD6000000000183AFF2001000000000000" + 2025 "0200001A1122334420010000000000000200001A33441122870045290000" + 2026 "000020010000000000000200001A33441122" 2027 // invalid unicast ether dst -> pass 2028 verifyProgramRun( 2029 APF_VERSION_6, 2030 program, 2031 HexDump.hexStringToByteArray(nonHostDstMacNsPkt), 2032 DROPPED_IPV6_NS_OTHER_HOST 2033 ) 2034 2035 // Using scapy to generate IPv6 NS packet: 2036 // eth = Ether(src="00:01:02:03:04:05", dst="33:33:ff:03:02:01") 2037 // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255) 2038 // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") 2039 // pkt = eth/ip6/icmp6 2040 val nonMcastDstMacNsPkt = "3333ff03020100010203040586DD6000000000183AFF2001000000000000" + 2041 "0200001A1122334420010000000000000200001A33441122870045290000" + 2042 "000020010000000000000200001A33441122" 2043 // mcast dst mac is not one of solicited mcast mac derived from one of device's ip -> pass 2044 verifyProgramRun( 2045 APF_VERSION_6, 2046 program, 2047 HexDump.hexStringToByteArray(nonMcastDstMacNsPkt), 2048 DROPPED_IPV6_NS_OTHER_HOST 2049 ) 2050 2051 // Using scapy to generate IPv6 NS packet: 2052 // eth = Ether(src="00:01:02:03:04:05", dst="33:33:ff:44:11:22") 2053 // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255) 2054 // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") 2055 // pkt = eth/ip6/icmp6 2056 val hostMcastDstMacNsPkt = "3333ff44112200010203040586DD6000000000183AFF2001000000000000" + 2057 "0200001A1122334420010000000000000200001A33441122870045290000" + 2058 "000020010000000000000200001A33441122" 2059 // mcast dst mac is one of solicited mcast mac derived from one of device's ip -> pass 2060 verifyProgramRun( 2061 APF_VERSION_6, 2062 program, 2063 HexDump.hexStringToByteArray(hostMcastDstMacNsPkt), 2064 PASSED_IPV6_ICMP 2065 ) 2066 2067 // Using scapy to generate IPv6 NS packet: 2068 // eth = Ether(src="00:01:02:03:04:05", dst="FF:FF:FF:FF:FF:FF") 2069 // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255) 2070 // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") 2071 // pkt = eth/ip6/icmp6 2072 val broadcastNsPkt = "FFFFFFFFFFFF00010203040586DD6000000000183AFF2001000000000000" + 2073 "0200001A1122334420010000000000000200001A33441122870045290000" + 2074 "000020010000000000000200001A33441122" 2075 // mcast dst mac is broadcast address -> pass 2076 verifyProgramRun( 2077 APF_VERSION_6, 2078 program, 2079 HexDump.hexStringToByteArray(broadcastNsPkt), 2080 PASSED_IPV6_ICMP 2081 ) 2082 2083 // validate IPv6 dst address check 2084 2085 // Using scapy to generate IPv6 NS packet: 2086 // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") 2087 // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255) 2088 // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") 2089 // pkt = eth/ip6/icmp6 2090 val validHostDstIpNsPkt = "02030405060700010203040586DD6000000000183AFF200100000000000" + 2091 "00200001A1122334420010000000000000200001A334411228700452900" + 2092 "00000020010000000000000200001A33441122" 2093 // dst ip is one of device's ip -> Pass 2094 verifyProgramRun( 2095 APF_VERSION_6, 2096 program, 2097 HexDump.hexStringToByteArray(validHostDstIpNsPkt), 2098 PASSED_IPV6_ICMP 2099 ) 2100 2101 // Using scapy to generate IPv6 NS packet: 2102 // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") 2103 // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::100:1b:aabb:ccdd", hlim=255) 2104 // icmp6 = ICMPv6ND_NS(tgt="2001::100:1b:aabb:ccdd") 2105 // pkt = eth/ip6/icmp6 2106 val validHostAnycastDstIpNsPkt = "02030405060700010203040586DD6000000000183AFF20010000" + 2107 "000000000200001A1122334420010000000000000100001BAABB" + 2108 "CCDD8700E0C00000000020010000000000000100001BAABBCCDD" 2109 // dst ip is device's anycast address -> Pass 2110 verifyProgramRun( 2111 APF_VERSION_6, 2112 program, 2113 HexDump.hexStringToByteArray(validHostAnycastDstIpNsPkt), 2114 PASSED_IPV6_ICMP 2115 ) 2116 2117 // Using scapy to generate IPv6 NS packet: 2118 // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") 2119 // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:4444:5555", hlim=255) 2120 // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") 2121 // pkt = eth/ip6/icmp6 2122 val nonHostUcastDstIpNsPkt = "02030405060700010203040586DD6000000000183AFF200100000000" + 2123 "00000200001A1122334420010000000000000200001A444455558700" + 2124 "EFF50000000020010000000000000200001A33441122" 2125 // unicast dst ip is not one of device's ip -> pass 2126 verifyProgramRun( 2127 APF_VERSION_6, 2128 program, 2129 HexDump.hexStringToByteArray(nonHostUcastDstIpNsPkt), 2130 DROPPED_IPV6_NS_OTHER_HOST 2131 ) 2132 2133 // Using scapy to generate IPv6 NS packet: 2134 // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") 2135 // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="ff02::1:ff44:1133", hlim=255) 2136 // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") 2137 // pkt = eth/ip6/icmp6 2138 val nonHostMcastDstIpNsPkt = "02030405060700010203040586DD6000000000183AFF200100000000" + 2139 "00000200001A11223344FF0200000000000000000001FF4411338700" + 2140 "9C2E0000000020010000000000000200001A33441122" 2141 // mcast dst ip is not one of solicited mcast ip derived from one of device's ip -> pass 2142 verifyProgramRun( 2143 APF_VERSION_6, 2144 program, 2145 HexDump.hexStringToByteArray(nonHostMcastDstIpNsPkt), 2146 DROPPED_IPV6_NS_OTHER_HOST 2147 ) 2148 2149 // Using scapy to generate IPv6 NS packet: 2150 // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") 2151 // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="ff02::1:ff44:1122", hlim=255) 2152 // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") 2153 // pkt = eth/ip6/icmp6 2154 val hostMcastDstIpNsPkt = "02030405060700010203040586DD6000000000183AFF200100000000" + 2155 "00000200001A11223344FF0200000000000000000001FF4411228700" + 2156 "9C2E0000000020010000000000000200001A33441122" 2157 // mcast dst ip is one of solicited mcast ip derived from one of device's ip -> pass 2158 verifyProgramRun( 2159 APF_VERSION_6, 2160 program, 2161 HexDump.hexStringToByteArray(hostMcastDstIpNsPkt), 2162 PASSED_IPV6_ICMP 2163 ) 2164 2165 // validate IPv6 NS payload check 2166 2167 // Using scapy to generate IPv6 NS packet: 2168 // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") 2169 // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255, plen=20) 2170 // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") 2171 // icmp6_opt = ICMPv6NDOptSrcLLAddr(lladdr="01:02:03:04:05:06") 2172 // pkt = eth/ip6/icmp6/icmp6_opt 2173 val shortNsPkt = "02030405060700010203040586DD6000000000143AFF20010000000000000200001A1" + 2174 "122334420010000000000000200001A3344112287003B140000000020010000000000" + 2175 "000200001A334411220101010203040506" 2176 // payload len < 24 -> drop 2177 verifyProgramRun( 2178 APF_VERSION_6, 2179 program, 2180 HexDump.hexStringToByteArray(shortNsPkt), 2181 DROPPED_IPV6_NS_INVALID 2182 ) 2183 2184 // Using scapy to generate IPv6 NS packet: 2185 // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") 2186 // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255) 2187 // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") 2188 // icmp6_opt_1 = ICMPv6NDOptSrcLLAddr(lladdr="01:02:03:04:05:06") 2189 // icmp6_opt_2 = ICMPv6NDOptUnknown(type=14, len=6, data='\x11\x22\x33\x44\x55\x66') 2190 // pkt = eth/ip6/icmp6/icmp6_opt_1/icmp6_opt_2 2191 val longNsPkt = "02030405060700010203040586DD6000000000283AFF20010000000000000200001A11" + 2192 "22334420010000000000000200001A3344112287009339000000002001000000000000" + 2193 "0200001A3344112201010102030405060E06112233445566" 2194 // payload len > 32 -> pass 2195 verifyProgramRun( 2196 APF_VERSION_6, 2197 program, 2198 HexDump.hexStringToByteArray(longNsPkt), 2199 PASSED_IPV6_NS_MULTIPLE_OPTIONS 2200 ) 2201 2202 // Using scapy to generate IPv6 NS packet: 2203 // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") 2204 // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255) 2205 // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:4444:5555") 2206 // icmp6_opt = ICMPv6NDOptSrcLLAddr(lladdr="01:02:03:04:05:06") 2207 // pkt = eth/ip6/icmp6/icmp6_opt 2208 val otherHostNsPkt = "02030405060700010203040586DD6000000000203AFF200100000000000002000" + 2209 "01A1122334420010000000000000200001A334411228700E5E000000000200100" + 2210 "00000000000200001A444455550101010203040506" 2211 // target ip is not one of device's ip -> drop 2212 verifyProgramRun( 2213 APF_VERSION_6, 2214 program, 2215 HexDump.hexStringToByteArray(otherHostNsPkt), 2216 DROPPED_IPV6_NS_OTHER_HOST 2217 ) 2218 2219 // Using scapy to generate IPv6 NS packet: 2220 // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") 2221 // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=20) 2222 // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122") 2223 // icmp6_opt = ICMPv6NDOptSrcLLAddr(lladdr="01:02:03:04:05:06") 2224 // pkt = eth/ip6/icmp6/icmp6_opt 2225 val invalidHoplimitNsPkt = "02030405060700010203040586DD6000000000203A14200100000000000" + 2226 "00200001A1122334420010000000000000200001A3344112287003B1400" + 2227 "00000020010000000000000200001A334411220101010203040506" 2228 // hoplimit is not 255 -> drop 2229 verifyProgramRun( 2230 APF_VERSION_6, 2231 program, 2232 HexDump.hexStringToByteArray(invalidHoplimitNsPkt), 2233 DROPPED_IPV6_NS_INVALID 2234 ) 2235 2236 // Using scapy to generate IPv6 NS packet: 2237 // eth = Ether(src="00:01:02:03:04:05", dst="02:03:04:05:06:07") 2238 // ip6 = IPv6(src="2001::200:1a:1122:3344", dst="2001::200:1a:3344:1122", hlim=255) 2239 // icmp6 = ICMPv6ND_NS(tgt="2001::200:1a:3344:1122", code=5) 2240 // icmp6_opt = ICMPv6NDOptSrcLLAddr(lladdr="01:02:03:04:05:06") 2241 // pkt = eth/ip6/icmp6/icmp6_opt 2242 val invalidIcmpCodeNsPkt = "02030405060700010203040586DD6000000000203AFF200100000000000" + 2243 "00200001A1122334420010000000000000200001A3344112287053B0F00" + 2244 "00000020010000000000000200001A334411220101010203040506" 2245 // icmp6 code is not 0 -> drop 2246 verifyProgramRun( 2247 APF_VERSION_6, 2248 program, 2249 HexDump.hexStringToByteArray(invalidIcmpCodeNsPkt), 2250 DROPPED_IPV6_NS_INVALID 2251 ) 2252 2253 apfFilter.shutdown() 2254 } 2255 2256 @Test testApfProgramUpdatenull2257 fun testApfProgramUpdate() { 2258 val apfFilter = 2259 ApfFilter( 2260 context, 2261 getDefaultConfig(), 2262 ifParams, 2263 ipClientCallback, 2264 metrics, 2265 dependencies 2266 ) 2267 2268 verify(ipClientCallback, times(2)).installPacketFilter(any()) 2269 // add IPv4 address, expect to have apf program update 2270 val lp = LinkProperties() 2271 val linkAddress = LinkAddress(InetAddress.getByAddress(hostIpv4Address), 24) 2272 lp.addLinkAddress(linkAddress) 2273 apfFilter.setLinkProperties(lp) 2274 verify(ipClientCallback, times(3)).installPacketFilter(any()) 2275 2276 // add the same IPv4 address, expect to have no apf program update 2277 apfFilter.setLinkProperties(lp) 2278 verify(ipClientCallback, times(3)).installPacketFilter(any()) 2279 2280 // add IPv6 addresses, expect to have apf program update 2281 for (addr in hostIpv6Addresses) { 2282 lp.addLinkAddress(LinkAddress(InetAddress.getByAddress(addr), 64)) 2283 } 2284 2285 apfFilter.setLinkProperties(lp) 2286 verify(ipClientCallback, times(4)).installPacketFilter(any()) 2287 2288 // add the same IPv6 addresses, expect to have no apf program update 2289 apfFilter.setLinkProperties(lp) 2290 verify(ipClientCallback, times(4)).installPacketFilter(any()) 2291 2292 // add more tentative IPv6 addresses, expect to have apf program update 2293 for (addr in hostIpv6TentativeAddresses) { 2294 lp.addLinkAddress(LinkAddress(InetAddress.getByAddress(addr), 64, IFA_F_TENTATIVE, 0)) 2295 } 2296 2297 apfFilter.setLinkProperties(lp) 2298 verify(ipClientCallback, times(5)).installPacketFilter(any()) 2299 2300 // add the same IPv6 addresses, expect to have no apf program update 2301 apfFilter.setLinkProperties(lp) 2302 verify(ipClientCallback, times(5)).installPacketFilter(any()) 2303 apfFilter.shutdown() 2304 } 2305 verifyProgramRunnull2306 private fun verifyProgramRun( 2307 version: Int, 2308 program: ByteArray, 2309 pkt: ByteArray, 2310 targetCnt: Counter, 2311 cntMap: MutableMap<Counter, Long> = mutableMapOf(), 2312 dataRegion: ByteArray = ByteArray(Counter.totalSize()) { 0 }, 2313 incTotal: Boolean = true, 2314 result: Int = if (targetCnt.name.startsWith("PASSED")) PASS else DROP 2315 ) { 2316 assertVerdict(version, result, program, pkt, dataRegion) 2317 cntMap[targetCnt] = cntMap.getOrDefault(targetCnt, 0) + 1 2318 if (incTotal) { 2319 cntMap[TOTAL_PACKETS] = cntMap.getOrDefault(TOTAL_PACKETS, 0) + 1 2320 } 2321 val errMsg = "Counter is not increased properly. To debug: \n" + 2322 " apf_run --program ${HexDump.toHexString(program)} " + 2323 "--packet ${HexDump.toHexString(pkt)} " + 2324 "--data ${HexDump.toHexString(dataRegion)} --age 0 " + 2325 "${if (version == APF_VERSION_6) "--v6" else "" } --trace | less \n" 2326 assertEquals(cntMap, decodeCountersIntoMap(dataRegion), errMsg) 2327 } 2328 decodeCountersIntoMapnull2329 private fun decodeCountersIntoMap(counterBytes: ByteArray): Map<Counter, Long> { 2330 val counters = Counter::class.java.enumConstants 2331 val ret = HashMap<Counter, Long>() 2332 val skippedCounters = setOf(APF_PROGRAM_ID, APF_VERSION) 2333 // starting from index 2 to skip the endianness mark 2334 for (c in listOf(*counters).subList(2, counters.size)) { 2335 if (c in skippedCounters) continue 2336 val value = ApfCounterTracker.getCounterValue(counterBytes, c) 2337 if (value != 0L) { 2338 ret[c] = value 2339 } 2340 } 2341 return ret 2342 } 2343 encodeInstructionnull2344 private fun encodeInstruction(opcode: Int, immLength: Int, register: Int): Byte { 2345 val immLengthEncoding = if (immLength == 4) 3 else immLength 2346 return opcode.shl(3).or(immLengthEncoding.shl(1)).or(register).toByte() 2347 } 2348 ByteArraynull2349 private fun ByteArray.skipDataAndDebug(): ByteArray { 2350 assertEquals( 2351 listOf( 2352 encodeInstruction(14, 2, 1), 2353 0, 2354 0, 2355 encodeInstruction(21, 1, 0), 2356 48 2357 // the actual exception buffer size is not checked here. 2358 ), 2359 this.take(5) 2360 ) 2361 return this.drop(7).toByteArray() 2362 } 2363 getDefaultConfignull2364 private fun getDefaultConfig(apfVersion: Int = APF_VERSION_6): ApfFilter.ApfConfiguration { 2365 val config = ApfFilter.ApfConfiguration() 2366 config.apfCapabilities = 2367 ApfCapabilities(apfVersion, 4096, ARPHRD_ETHER) 2368 config.multicastFilter = false 2369 config.ieee802_3Filter = false 2370 config.ethTypeBlackList = IntArray(0) 2371 config.shouldHandleArpOffload = true 2372 return config 2373 } 2374 } 2375