Merge "Fix lint errors and adding nullability annotations in PacketReflector"
diff --git a/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkAddressMessage.java b/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkAddressMessage.java
index c07cec0..31c3a2e 100644
--- a/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkAddressMessage.java
+++ b/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkAddressMessage.java
@@ -58,12 +58,20 @@
     @Nullable
     private StructIfacacheInfo mIfacacheInfo;
 
-    private RtNetlinkAddressMessage(@NonNull StructNlMsgHdr header) {
+    @VisibleForTesting
+    public RtNetlinkAddressMessage(@NonNull final StructNlMsgHdr header,
+            @NonNull final StructIfaddrMsg ifaddrMsg,
+            @NonNull final InetAddress ipAddress,
+            @Nullable final StructIfacacheInfo structIfacacheInfo,
+            int flags) {
         super(header);
-        mIfaddrmsg = null;
-        mIpAddress = null;
-        mIfacacheInfo = null;
-        mFlags = 0;
+        mIfaddrmsg = ifaddrMsg;
+        mIpAddress = ipAddress;
+        mIfacacheInfo = structIfacacheInfo;
+        mFlags = flags;
+    }
+    private RtNetlinkAddressMessage(@NonNull StructNlMsgHdr header) {
+        this(header, null, null, null, 0);
     }
 
     public int getFlags() {
diff --git a/staticlibs/device/com/android/net/module/util/netlink/StructIfaddrMsg.java b/staticlibs/device/com/android/net/module/util/netlink/StructIfaddrMsg.java
index 9196feb..2802726 100644
--- a/staticlibs/device/com/android/net/module/util/netlink/StructIfaddrMsg.java
+++ b/staticlibs/device/com/android/net/module/util/netlink/StructIfaddrMsg.java
@@ -18,6 +18,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
 
 import com.android.net.module.util.Struct;
 import com.android.net.module.util.Struct.Field;
@@ -49,7 +50,8 @@
     @Field(order = 4, type = Type.S32)
     public final int index;
 
-    StructIfaddrMsg(short family, short prefixLen, short flags, short scope, int index) {
+    @VisibleForTesting
+    public StructIfaddrMsg(short family, short prefixLen, short flags, short scope, int index) {
         this.family = family;
         this.prefixLen = prefixLen;
         this.flags = flags;
diff --git a/staticlibs/device/com/android/net/module/util/structs/IaPdOption.java b/staticlibs/device/com/android/net/module/util/structs/IaPdOption.java
index 5a09c40..dbf79dc 100644
--- a/staticlibs/device/com/android/net/module/util/structs/IaPdOption.java
+++ b/staticlibs/device/com/android/net/module/util/structs/IaPdOption.java
@@ -50,15 +50,15 @@
     public static final int LENGTH = 12; // option length excluding IA_PD options
 
     @Field(order = 0, type = Type.S16)
-    public short code;
+    public final short code;
     @Field(order = 1, type = Type.S16)
-    public short length;
+    public final short length;
     @Field(order = 2, type = Type.U32)
-    public long id;
+    public final long id;
     @Field(order = 3, type = Type.U32)
-    public long t1;
+    public final long t1;
     @Field(order = 4, type = Type.U32)
-    public long t2;
+    public final long t2;
 
     IaPdOption(final short code, final short length, final long id, final long t1,
             final long t2) {
diff --git a/staticlibs/device/com/android/net/module/util/structs/IaPrefixOption.java b/staticlibs/device/com/android/net/module/util/structs/IaPrefixOption.java
index 1ac21ff..cd974e6 100644
--- a/staticlibs/device/com/android/net/module/util/structs/IaPrefixOption.java
+++ b/staticlibs/device/com/android/net/module/util/structs/IaPrefixOption.java
@@ -55,17 +55,17 @@
     public static final int LENGTH = 25; // option length excluding IAprefix-options
 
     @Field(order = 0, type = Type.S16)
-    public short code;
+    public final short code;
     @Field(order = 1, type = Type.S16)
-    public short length;
+    public final short length;
     @Field(order = 2, type = Type.U32)
-    public long preferred;
+    public final long preferred;
     @Field(order = 3, type = Type.U32)
-    public long valid;
+    public final long valid;
     @Field(order = 4, type = Type.U8)
-    public short prefixLen;
+    public final short prefixLen;
     @Field(order = 5, type = Type.ByteArray, arraysize = 16)
-    public byte[] prefix;
+    public final byte[] prefix;
 
     IaPrefixOption(final short code, final short length, final long preferred,
             final long valid, final short prefixLen, final byte[] prefix) {
diff --git a/staticlibs/native/bpf_headers/include/bpf/BpfClassic.h b/staticlibs/native/bpf_headers/include/bpf/BpfClassic.h
new file mode 100644
index 0000000..9b38dee
--- /dev/null
+++ b/staticlibs/native/bpf_headers/include/bpf/BpfClassic.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+// Accept the full packet
+#define BPF_ACCEPT BPF_STMT(BPF_RET | BPF_K, 0xFFFFFFFF)
+
+// Reject the packet
+#define BPF_REJECT BPF_STMT(BPF_RET | BPF_K, 0)
+
+// *TWO* instructions: compare and if equal jump over the reject statement
+#define BPF2_REJECT_IF_NOT_EQUAL(v) \
+	BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, (v), 1, 0), \
+	BPF_REJECT
+
+// 8-bit load relative to start of link layer (mac/ethernet) header.
+#define BPF_LOAD_MAC_RELATIVE_U8(ofs) \
+	BPF_STMT(BPF_LD | BPF_B | BPF_ABS, (__u32)SKF_LL_OFF + (ofs))
+
+// Big/Network Endian 16-bit load relative to start of link layer (mac/ethernet) header.
+#define BPF_LOAD_MAC_RELATIVE_BE16(ofs) \
+	BPF_STMT(BPF_LD | BPF_H | BPF_ABS, (__u32)SKF_LL_OFF + (ofs))
+
+// Big/Network Endian 32-bit load relative to start of link layer (mac/ethernet) header.
+#define BPF_LOAD_MAC_RELATIVE_BE32(ofs) \
+	BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (__u32)SKF_LL_OFF + (ofs))
+
+// 8-bit load relative to start of network (IPv4/IPv6) header.
+#define BPF_LOAD_NET_RELATIVE_U8(ofs) \
+	BPF_STMT(BPF_LD | BPF_B | BPF_ABS, (__u32)SKF_NET_OFF + (ofs))
+
+// Big/Network Endian 16-bit load relative to start of network (IPv4/IPv6) header.
+#define BPF_LOAD_NET_RELATIVE_BE16(ofs) \
+	BPF_STMT(BPF_LD | BPF_H | BPF_ABS, (__u32)SKF_NET_OFF + (ofs))
+
+// Big/Network Endian 32-bit load relative to start of network (IPv4/IPv6) header.
+#define BPF_LOAD_NET_RELATIVE_BE32(ofs) \
+	BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (__u32)SKF_NET_OFF + (ofs))
+
+#define field_sizeof(struct_type,field) sizeof(((struct_type *)0)->field)
+
+// 8-bit load from IPv4 header field.
+#define BPF_LOAD_IPV4_U8(field) \
+	BPF_LOAD_NET_RELATIVE_U8(({ \
+	  _Static_assert(field_sizeof(struct iphdr, field) == 1, "field of wrong size"); \
+	  offsetof(iphdr, field); \
+	}))
+
+// Big/Network Endian 16-bit load from IPv4 header field.
+#define BPF_LOAD_IPV4_BE16(field) \
+	BPF_LOAD_NET_RELATIVE_BE16(({ \
+	  _Static_assert(field_sizeof(struct iphdr, field) == 2, "field of wrong size"); \
+	  offsetof(iphdr, field); \
+	}))
+
+// Big/Network Endian 32-bit load from IPv4 header field.
+#define BPF_LOAD_IPV4_BE32(field) \
+	BPF_LOAD_NET_RELATIVE_BE32(({ \
+	  _Static_assert(field_sizeof(struct iphdr, field) == 4, "field of wrong size"); \
+	  offsetof(iphdr, field); \
+	}))
+
+// 8-bit load from IPv6 header field.
+#define BPF_LOAD_IPV6_U8(field) \
+	BPF_LOAD_NET_RELATIVE_U8(({ \
+	  _Static_assert(field_sizeof(struct ipv6hdr, field) == 1, "field of wrong size"); \
+	  offsetof(ipv6hdr, field); \
+	}))
+
+// Big/Network Endian 16-bit load from IPv6 header field.
+#define BPF_LOAD_IPV6_BE16(field) \
+	BPF_LOAD_NET_RELATIVE_BE16(({ \
+	  _Static_assert(field_sizeof(struct ipv6hdr, field) == 2, "field of wrong size"); \
+	  offsetof(ipv6hdr, field); \
+	}))
+
+// Big/Network Endian 32-bit load from IPv6 header field.
+#define BPF_LOAD_IPV6_BE32(field) \
+	BPF_LOAD_NET_RELATIVE_BE32(({ \
+	  _Static_assert(field_sizeof(struct ipv6hdr, field) == 4, "field of wrong size"); \
+	  offsetof(ipv6hdr, field); \
+	}))
diff --git a/staticlibs/native/bpf_headers/include/bpf/BpfUtils.h b/staticlibs/native/bpf_headers/include/bpf/BpfUtils.h
index e2cb676..206acba 100644
--- a/staticlibs/native/bpf_headers/include/bpf/BpfUtils.h
+++ b/staticlibs/native/bpf_headers/include/bpf/BpfUtils.h
@@ -33,17 +33,26 @@
 namespace android {
 namespace bpf {
 
+// See kernel's net/core/sock_diag.c __sock_gen_cookie()
+// the implementation of which guarantees 0 will never be returned,
+// primarily because 0 is used to mean not yet initialized,
+// and socket cookies are only assigned on first fetch.
 constexpr const uint64_t NONEXISTENT_COOKIE = 0;
 
 static inline uint64_t getSocketCookie(int sockFd) {
     uint64_t sock_cookie;
     socklen_t cookie_len = sizeof(sock_cookie);
-    int res = getsockopt(sockFd, SOL_SOCKET, SO_COOKIE, &sock_cookie, &cookie_len);
-    if (res < 0) {
-        res = -errno;
-        ALOGE("Failed to get socket cookie: %s\n", strerror(errno));
-        errno = -res;
-        // 0 is an invalid cookie. See sock_gen_cookie.
+    if (getsockopt(sockFd, SOL_SOCKET, SO_COOKIE, &sock_cookie, &cookie_len)) {
+        // Failure is almost certainly either EBADF or ENOTSOCK
+        const int err = errno;
+        ALOGE("Failed to get socket cookie: %s\n", strerror(err));
+        errno = err;
+        return NONEXISTENT_COOKIE;
+    }
+    if (cookie_len != sizeof(sock_cookie)) {
+        // This probably cannot actually happen, but...
+        ALOGE("Failed to get socket cookie: len %d != 8\n", cookie_len);
+        errno = 523; // EBADCOOKIE: kernel internal, seems reasonable enough...
         return NONEXISTENT_COOKIE;
     }
     return sock_cookie;
@@ -56,19 +65,19 @@
     //
     // Linux 4.14/4.19/5.4/5.10/5.15 (and 5.18) still have this same behaviour.
     // see net/key/af_key.c: pfkey_release() -> synchronize_rcu()
-    int pfSocket = socket(AF_KEY, SOCK_RAW | SOCK_CLOEXEC, PF_KEY_V2);
+    const int pfSocket = socket(AF_KEY, SOCK_RAW | SOCK_CLOEXEC, PF_KEY_V2);
 
     if (pfSocket < 0) {
-        int ret = -errno;
-        ALOGE("create PF_KEY socket failed: %s", strerror(errno));
-        return ret;
+        const int err = errno;
+        ALOGE("create PF_KEY socket failed: %s", strerror(err));
+        return -err;
     }
 
     // When closing socket, synchronize_rcu() gets called in sock_release().
     if (close(pfSocket)) {
-        int ret = -errno;
-        ALOGE("failed to close the PF_KEY socket: %s", strerror(errno));
-        return ret;
+        const int err = errno;
+        ALOGE("failed to close the PF_KEY socket: %s", strerror(err));
+        return -err;
     }
     return 0;
 }
@@ -79,10 +88,8 @@
             .rlim_cur = 1073741824,  // 1 GiB
             .rlim_max = 1073741824,  // 1 GiB
     };
-    int res = setrlimit(RLIMIT_MEMLOCK, &limit);
-    if (res) {
-        ALOGE("Failed to set the default MEMLOCK rlimit: %s", strerror(errno));
-    }
+    const int res = setrlimit(RLIMIT_MEMLOCK, &limit);
+    if (res) ALOGE("Failed to set the default MEMLOCK rlimit: %s", strerror(errno));
     return res;
 }
 
diff --git a/staticlibs/native/ip_checksum/checksum.c b/staticlibs/native/ip_checksum/checksum.c
index 04217a7..5641fad 100644
--- a/staticlibs/native/ip_checksum/checksum.c
+++ b/staticlibs/native/ip_checksum/checksum.c
@@ -32,20 +32,16 @@
  *   len         - length of data
  */
 uint32_t ip_checksum_add(uint32_t current, const void* data, int len) {
-    uint32_t checksum = current;
-    int left = len;
     const uint16_t* data_16 = data;
 
-    while (left > 1) {
-        checksum += *data_16;
+    while (len >= 2) {
+        current += *data_16;
         data_16++;
-        left -= 2;
+        len -= 2;
     }
-    if (left) {
-        checksum += *(uint8_t*)data_16;
-    }
+    if (len) current += *(uint8_t*)data_16;  // assumes little endian!
 
-    return checksum;
+    return current;
 }
 
 /* function: ip_checksum_fold
@@ -54,9 +50,8 @@
  *   returns: the folded checksum in network byte order
  */
 uint16_t ip_checksum_fold(uint32_t temp_sum) {
-    while (temp_sum > 0xffff) {
-        temp_sum = (temp_sum >> 16) + (temp_sum & 0xFFFF);
-    }
+    temp_sum = (temp_sum >> 16) + (temp_sum & 0xFFFF);
+    temp_sum = (temp_sum >> 16) + (temp_sum & 0xFFFF);
     return temp_sum;
 }
 
@@ -75,12 +70,7 @@
  *   len  - length of data
  */
 uint16_t ip_checksum(const void* data, int len) {
-    // TODO: consider starting from 0xffff so the checksum of a buffer entirely consisting of zeros
-    // is correctly calculated as 0.
-    uint32_t temp_sum;
-
-    temp_sum = ip_checksum_add(0, data, len);
-    return ip_checksum_finish(temp_sum);
+    return ip_checksum_finish(ip_checksum_add(0xFFFF, data, len));
 }
 
 /* function: ipv6_pseudo_header_checksum
@@ -92,7 +82,6 @@
 uint32_t ipv6_pseudo_header_checksum(const struct ip6_hdr* ip6, uint32_t len, uint8_t protocol) {
     uint32_t checksum_len = htonl(len);
     uint32_t checksum_next = htonl(protocol);
-
     uint32_t current = 0;
 
     current = ip_checksum_add(current, &(ip6->ip6_src), sizeof(struct in6_addr));
@@ -109,11 +98,8 @@
  *   len     - the transport length (transport header + payload)
  */
 uint32_t ipv4_pseudo_header_checksum(const struct iphdr* ip, uint16_t len) {
-    uint16_t temp_protocol, temp_length;
-
-    temp_protocol = htons(ip->protocol);
-    temp_length = htons(len);
-
+    uint16_t temp_protocol = htons(ip->protocol);
+    uint16_t temp_length = htons(len);
     uint32_t current = 0;
 
     current = ip_checksum_add(current, &(ip->saddr), sizeof(uint32_t));
@@ -135,7 +121,7 @@
     // Algorithm suggested in RFC 1624.
     // http://tools.ietf.org/html/rfc1624#section-3
     checksum = ~checksum;
-    uint16_t folded_sum = ip_checksum_fold(checksum + new_hdr_sum);
+    uint16_t folded_sum = ip_checksum_fold(new_hdr_sum + checksum);
     uint16_t folded_old = ip_checksum_fold(old_hdr_sum);
     if (folded_sum > folded_old) {
         return ~(folded_sum - folded_old);
diff --git a/staticlibs/native/ip_checksum/checksum.h b/staticlibs/native/ip_checksum/checksum.h
index 868217c..87393c9 100644
--- a/staticlibs/native/ip_checksum/checksum.h
+++ b/staticlibs/native/ip_checksum/checksum.h
@@ -12,11 +12,8 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- *
- * checksum.h - checksum functions
  */
-#ifndef __CHECKSUM_H__
-#define __CHECKSUM_H__
+#pragma once
 
 #include <netinet/ip.h>
 #include <netinet/ip6.h>
@@ -30,5 +27,3 @@
 uint32_t ipv4_pseudo_header_checksum(const struct iphdr* ip, uint16_t len);
 
 uint16_t ip_checksum_adjust(uint16_t checksum, uint32_t old_hdr_sum, uint32_t new_hdr_sum);
-
-#endif /* __CHECKSUM_H__ */
diff --git a/staticlibs/testutils/app/connectivitychecker/src/com/android/testutils/connectivitychecker/ConnectivityCheckTest.kt b/staticlibs/testutils/app/connectivitychecker/src/com/android/testutils/connectivitychecker/ConnectivityCheckTest.kt
index f34ca22..f72938d 100644
--- a/staticlibs/testutils/app/connectivitychecker/src/com/android/testutils/connectivitychecker/ConnectivityCheckTest.kt
+++ b/staticlibs/testutils/app/connectivitychecker/src/com/android/testutils/connectivitychecker/ConnectivityCheckTest.kt
@@ -29,10 +29,10 @@
 import com.android.testutils.RecorderCallback
 import com.android.testutils.TestableNetworkCallback
 import com.android.testutils.tryTest
-import org.junit.Test
-import org.junit.runner.RunWith
 import kotlin.test.assertTrue
 import kotlin.test.fail
+import org.junit.Test
+import org.junit.runner.RunWith
 
 @RunWith(AndroidJUnit4::class)
 class ConnectivityCheckTest {
@@ -76,7 +76,7 @@
                         .addTransportType(TRANSPORT_CELLULAR)
                         .addCapability(NET_CAPABILITY_INTERNET).build(), cb)
         tryTest {
-            cb.eventuallyExpectOrNull<RecorderCallback.CallbackEntry.Available>()
+            cb.poll { it is RecorderCallback.CallbackEntry.Available }
                     ?: fail("The device does not have mobile data available. Check that it is " +
                             "setup with a SIM card that has a working data plan, and that the " +
                             "APN configuration is valid.")
@@ -84,4 +84,4 @@
             cm.unregisterNetworkCallback(cb)
         }
     }
-}
\ No newline at end of file
+}
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/ConnectUtil.kt b/staticlibs/testutils/devicetests/com/android/testutils/ConnectUtil.kt
index 7b5ad01..71f7877 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/ConnectUtil.kt
+++ b/staticlibs/testutils/devicetests/com/android/testutils/ConnectUtil.kt
@@ -32,6 +32,7 @@
 import android.os.SystemClock
 import android.util.Log
 import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
+import com.android.testutils.RecorderCallback.CallbackEntry
 import java.util.concurrent.CompletableFuture
 import java.util.concurrent.TimeUnit
 import kotlin.test.assertNotNull
@@ -72,9 +73,7 @@
                 val config = getOrCreateWifiConfiguration()
                 connectToWifiConfig(config)
             }
-            val cb = callback.eventuallyExpectOrNull<RecorderCallback.CallbackEntry.Available>(
-                    timeoutMs = WIFI_CONNECT_TIMEOUT_MS)
-
+            val cb = callback.poll(WIFI_CONNECT_TIMEOUT_MS) { it is CallbackEntry.Available }
             assertNotNull(cb, "Could not connect to a wifi access point within " +
                     "$WIFI_CONNECT_TIMEOUT_MS ms. Check that the test device has a wifi network " +
                     "configured, and that the test access point is functioning properly.")
@@ -201,4 +200,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/TestableNetworkCallback.kt b/staticlibs/testutils/devicetests/com/android/testutils/TestableNetworkCallback.kt
index 485799c..e7d86e0 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/TestableNetworkCallback.kt
+++ b/staticlibs/testutils/devicetests/com/android/testutils/TestableNetworkCallback.kt
@@ -220,7 +220,8 @@
      * Long.MAX_VALUE.
      */
     @JvmOverloads
-    fun poll(timeoutMs: Long = defaultTimeoutMs): CallbackEntry? = history.poll(timeoutMs)
+    fun poll(timeoutMs: Long = defaultTimeoutMs, predicate: (CallbackEntry) -> Boolean = { true }) =
+            history.poll(timeoutMs, predicate)
 
     /**
      * Get the next callback or throw if timeout.
@@ -385,7 +386,7 @@
         timeoutMs: Long = defaultTimeoutMs,
         from: Int = mark,
         crossinline predicate: (T) -> Boolean = { true }
-    ): T = eventuallyExpectOrNull(timeoutMs, from, predicate).also {
+    ): T = history.poll(timeoutMs, from) { it is T && predicate(it) }.also {
         assertNotNull(it, "Callback ${T::class} not received within ${timeoutMs}ms")
     } as T
 
@@ -407,7 +408,7 @@
         assertNotNull(it, "Callback ${type.java} not received within ${timeoutMs}ms")
     } as T
 
-    // TODO (b/157405399) straighten and unify the method names
+    // TODO (b/157405399) remove this method when there are no longer any uses of it.
     inline fun <reified T : CallbackEntry> eventuallyExpectOrNull(
         timeoutMs: Long = defaultTimeoutMs,
         from: Int = mark,