Split netlink ack check code to individual function

Upcoming CL uses this function

Bug: 270298713
Test: atest NetworkStaticLibTests
Change-Id: I4b969024206b3bc58965e44849e426cc91344425
diff --git a/staticlibs/device/com/android/net/module/util/netlink/NetlinkUtils.java b/staticlibs/device/com/android/net/module/util/netlink/NetlinkUtils.java
index ae16cf8..d4bf14a 100644
--- a/staticlibs/device/com/android/net/module/util/netlink/NetlinkUtils.java
+++ b/staticlibs/device/com/android/net/module/util/netlink/NetlinkUtils.java
@@ -36,6 +36,7 @@
 import android.util.Log;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -81,6 +82,54 @@
     }
 
     /**
+     * Parse netlink error message
+     *
+     * @param bytes byteBuffer to parse netlink error message
+     * @return NetlinkErrorMessage if bytes contains valid NetlinkErrorMessage, else {@code null}
+     */
+    @Nullable
+    private static NetlinkErrorMessage parseNetlinkErrorMessage(ByteBuffer bytes) {
+        final StructNlMsgHdr nlmsghdr = StructNlMsgHdr.parse(bytes);
+        if (nlmsghdr == null || nlmsghdr.nlmsg_type != NetlinkConstants.NLMSG_ERROR) {
+            return null;
+        }
+        return NetlinkErrorMessage.parse(nlmsghdr, bytes);
+    }
+
+    /**
+     * Receive netlink ack message and check error
+     *
+     * @param fd fd to read netlink message
+     */
+    public static void receiveNetlinkAck(final FileDescriptor fd)
+            throws InterruptedIOException, ErrnoException {
+        final ByteBuffer bytes = recvMessage(fd, DEFAULT_RECV_BUFSIZE, IO_TIMEOUT_MS);
+        // recvMessage() guaranteed to not return null if it did not throw.
+        final NetlinkErrorMessage response = parseNetlinkErrorMessage(bytes);
+        if (response != null && response.getNlMsgError() != null) {
+            final int errno = response.getNlMsgError().error;
+            if (errno != 0) {
+                // TODO: consider ignoring EINVAL (-22), which appears to be
+                // normal when probing a neighbor for which the kernel does
+                // not already have / no longer has a link layer address.
+                Log.e(TAG, "receiveNetlinkAck, errmsg=" + response.toString());
+                // Note: convert kernel errnos (negative) into userspace errnos (positive).
+                throw new ErrnoException(response.toString(), Math.abs(errno));
+            }
+        } else {
+            final String errmsg;
+            if (response == null) {
+                bytes.position(0);
+                errmsg = "raw bytes: " + NetlinkConstants.hexify(bytes);
+            } else {
+                errmsg = response.toString();
+            }
+            Log.e(TAG, "receiveNetlinkAck, errmsg=" + errmsg);
+            throw new ErrnoException(errmsg, EPROTO);
+        }
+    }
+
+    /**
      * Send one netlink message to kernel via netlink socket.
      *
      * @param nlProto netlink protocol type.
@@ -93,31 +142,7 @@
         try {
             connectSocketToNetlink(fd);
             sendMessage(fd, msg, 0, msg.length, IO_TIMEOUT_MS);
-            final ByteBuffer bytes = recvMessage(fd, DEFAULT_RECV_BUFSIZE, IO_TIMEOUT_MS);
-            // recvMessage() guaranteed to not return null if it did not throw.
-            final NetlinkMessage response = NetlinkMessage.parse(bytes, nlProto);
-            if (response != null && response instanceof NetlinkErrorMessage
-                    && (((NetlinkErrorMessage) response).getNlMsgError() != null)) {
-                final int errno = ((NetlinkErrorMessage) response).getNlMsgError().error;
-                if (errno != 0) {
-                    // TODO: consider ignoring EINVAL (-22), which appears to be
-                    // normal when probing a neighbor for which the kernel does
-                    // not already have / no longer has a link layer address.
-                    Log.e(TAG, errPrefix + ", errmsg=" + response.toString());
-                    // Note: convert kernel errnos (negative) into userspace errnos (positive).
-                    throw new ErrnoException(response.toString(), Math.abs(errno));
-                }
-            } else {
-                final String errmsg;
-                if (response == null) {
-                    bytes.position(0);
-                    errmsg = "raw bytes: " + NetlinkConstants.hexify(bytes);
-                } else {
-                    errmsg = response.toString();
-                }
-                Log.e(TAG, errPrefix + ", errmsg=" + errmsg);
-                throw new ErrnoException(errmsg, EPROTO);
-            }
+            receiveNetlinkAck(fd);
         } catch (InterruptedIOException e) {
             Log.e(TAG, errPrefix, e);
             throw new ErrnoException(errPrefix, ETIMEDOUT, e);