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