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);