Use NetlinkUtil to process dump messages in InetDiagMessage.
Test: atest NetworkStaticLibTests:com.android.net.moduletests.util.netlink.InetDiagSocketTest
atest FrameworksNetTests:android.net.connectivity.com.android.server.ConnectivityServiceTest
Change-Id: I71545beea8e4d9d9993f473813017f76094dc2e0
diff --git a/staticlibs/device/com/android/net/module/util/netlink/InetDiagMessage.java b/staticlibs/device/com/android/net/module/util/netlink/InetDiagMessage.java
index 4f76577..c6a2042 100644
--- a/staticlibs/device/com/android/net/module/util/netlink/InetDiagMessage.java
+++ b/staticlibs/device/com/android/net/module/util/netlink/InetDiagMessage.java
@@ -61,6 +61,8 @@
import java.nio.ByteOrder;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
import java.util.function.Predicate;
/**
@@ -307,9 +309,8 @@
NetlinkUtils.receiveNetlinkAck(fd);
}
- private static void sendNetlinkDumpRequest(FileDescriptor fd, int proto, int states, int family)
- throws InterruptedIOException, ErrnoException {
- final byte[] dumpMsg = InetDiagMessage.inetDiagReqV2(
+ private static byte [] makeNetlinkDumpRequest(int proto, int states, int family) {
+ return InetDiagMessage.inetDiagReqV2(
proto,
null /* id */,
family,
@@ -318,51 +319,29 @@
0 /* pad */,
0 /* idiagExt */,
states);
- NetlinkUtils.sendMessage(fd, dumpMsg, 0, dumpMsg.length, IO_TIMEOUT_MS);
}
- private static int processNetlinkDumpAndDestroySockets(FileDescriptor dumpFd,
+ private static int processNetlinkDumpAndDestroySockets(byte[] dumpReq,
FileDescriptor destroyFd, int proto, Predicate<InetDiagMessage> filter)
- throws InterruptedIOException, ErrnoException {
- int destroyedSockets = 0;
-
- while (true) {
- final ByteBuffer buf = NetlinkUtils.recvMessage(
- dumpFd, DEFAULT_RECV_BUFSIZE, IO_TIMEOUT_MS);
-
- while (buf.remaining() > 0) {
- final int position = buf.position();
- final NetlinkMessage nlMsg = NetlinkMessage.parse(buf, NETLINK_INET_DIAG);
- if (nlMsg == null) {
- // Move to the position where parse started for error log.
- buf.position(position);
- Log.e(TAG, "Failed to parse netlink message: " + hexify(buf));
- break;
- }
-
- if (nlMsg.getHeader().nlmsg_type == NLMSG_DONE) {
- return destroyedSockets;
- }
-
- if (!(nlMsg instanceof InetDiagMessage)) {
- Log.wtf(TAG, "Received unexpected netlink message: " + nlMsg);
- continue;
- }
-
- final InetDiagMessage diagMsg = (InetDiagMessage) nlMsg;
- if (filter.test(diagMsg)) {
- try {
- sendNetlinkDestroyRequest(destroyFd, proto, diagMsg);
- destroyedSockets++;
- } catch (InterruptedIOException | ErrnoException e) {
- if (!(e instanceof ErrnoException
- && ((ErrnoException) e).errno == ENOENT)) {
- Log.e(TAG, "Failed to destroy socket: diagMsg=" + diagMsg + ", " + e);
- }
+ throws SocketException, InterruptedIOException, ErrnoException {
+ AtomicInteger destroyedSockets = new AtomicInteger(0);
+ Consumer<InetDiagMessage> handleNlDumpMsg = (diagMsg) -> {
+ if (filter.test(diagMsg)) {
+ try {
+ sendNetlinkDestroyRequest(destroyFd, proto, diagMsg);
+ destroyedSockets.getAndIncrement();
+ } catch (InterruptedIOException | ErrnoException e) {
+ if (!(e instanceof ErrnoException
+ && ((ErrnoException) e).errno == ENOENT)) {
+ Log.e(TAG, "Failed to destroy socket: diagMsg=" + diagMsg + ", " + e);
}
}
}
- }
+ };
+
+ NetlinkUtils.<InetDiagMessage>getAndProcessNetlinkDumpMessages(dumpReq,
+ NETLINK_INET_DIAG, InetDiagMessage.class, handleNlDumpMsg);
+ return destroyedSockets.get();
}
/**
@@ -420,31 +399,28 @@
private static void destroySockets(int proto, int states, Predicate<InetDiagMessage> filter)
throws ErrnoException, SocketException, InterruptedIOException {
- FileDescriptor dumpFd = null;
FileDescriptor destroyFd = null;
try {
- dumpFd = NetlinkUtils.createNetLinkInetDiagSocket();
destroyFd = NetlinkUtils.createNetLinkInetDiagSocket();
- connectToKernel(dumpFd);
connectToKernel(destroyFd);
for (int family : List.of(AF_INET, AF_INET6)) {
+ byte[] req = makeNetlinkDumpRequest(proto, states, family);
+
try {
- sendNetlinkDumpRequest(dumpFd, proto, states, family);
- } catch (InterruptedIOException | ErrnoException e) {
- Log.e(TAG, "Failed to send netlink dump request: " + e);
- continue;
- }
- final int destroyedSockets = processNetlinkDumpAndDestroySockets(
- dumpFd, destroyFd, proto, filter);
- Log.d(TAG, "Destroyed " + destroyedSockets + " sockets"
+ final int destroyedSockets = processNetlinkDumpAndDestroySockets(
+ req, destroyFd, proto, filter);
+ Log.d(TAG, "Destroyed " + destroyedSockets + " sockets"
+ ", proto=" + stringForProtocol(proto)
+ ", family=" + stringForAddressFamily(family)
+ ", states=" + states);
+ } catch (SocketException | InterruptedIOException | ErrnoException e) {
+ Log.e(TAG, "Failed to send netlink dump request or receive messages: " + e);
+ continue;
+ }
}
} finally {
- closeSocketQuietly(dumpFd);
closeSocketQuietly(destroyFd);
}
}
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 fafa5ee..7c2be2c 100644
--- a/staticlibs/device/com/android/net/module/util/netlink/NetlinkUtils.java
+++ b/staticlibs/device/com/android/net/module/util/netlink/NetlinkUtils.java
@@ -35,7 +35,6 @@
import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_DUMP;
import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-import android.net.ParseException;
import android.net.util.SocketUtils;
import android.system.ErrnoException;
import android.system.Os;
@@ -315,49 +314,20 @@
private NetlinkUtils() {}
- /**
- * Sends a netlink dump request and processes the returned dump messages
- *
- * @param <T> extends NetlinkMessage
- * @param dumpRequestMessage netlink dump request message to be sent
- * @param nlFamily netlink family
- * @param msgClass expected class of the netlink message
- * @param func function defined by caller to handle the dump messages
- * @throws SocketException when fails to create socket
- * @throws InterruptedIOException when fails to read the dumpFd
- * @throws ErrnoException when fails to send dump request
- * @throws ParseException when message can't be parsed
- */
- public static <T extends NetlinkMessage> void getAndProcessNetlinkDumpMessages(
- byte[] dumpRequestMessage, int nlFamily, Class<T> msgClass,
+ private static <T extends NetlinkMessage> void getAndProcessNetlinkDumpMessagesWithFd(
+ FileDescriptor fd, byte[] dumpRequestMessage, int nlFamily, Class<T> msgClass,
Consumer<T> func)
- throws SocketException, InterruptedIOException, ErrnoException, ParseException {
- // Create socket and send dump request
- final FileDescriptor fd;
- try {
- fd = netlinkSocketForProto(nlFamily);
- } catch (ErrnoException e) {
- Log.e(TAG, "Failed to create netlink socket " + e);
- throw e.rethrowAsSocketException();
- }
+ throws SocketException, InterruptedIOException, ErrnoException {
+ // connecToKernel throws ErrnoException and SocketException, should be handled by caller
+ connectToKernel(fd);
- try {
- connectToKernel(fd);
- } catch (ErrnoException | SocketException e) {
- Log.e(TAG, "Failed to connect netlink socket to kernel " + e);
- closeSocketQuietly(fd);
- return;
- }
-
- try {
- sendMessage(fd, dumpRequestMessage, 0, dumpRequestMessage.length, IO_TIMEOUT_MS);
- } catch (InterruptedIOException | ErrnoException e) {
- Log.e(TAG, "Failed to send dump request " + e);
- closeSocketQuietly(fd);
- throw e;
- }
+ // sendMessage throws InterruptedIOException and ErrnoException,
+ // should be handled by caller
+ sendMessage(fd, dumpRequestMessage, 0, dumpRequestMessage.length, IO_TIMEOUT_MS);
while (true) {
+ // recvMessage throws ErrnoException, InterruptedIOException
+ // should be handled by caller
final ByteBuffer buf = recvMessage(
fd, NetlinkUtils.DEFAULT_RECV_BUFSIZE, IO_TIMEOUT_MS);
@@ -368,17 +338,15 @@
// Move to the position where parse started for error log.
buf.position(position);
Log.e(TAG, "Failed to parse netlink message: " + hexify(buf));
- closeSocketQuietly(fd);
- throw new ParseException("Failed to parse netlink message");
+ break;
}
if (nlMsg.getHeader().nlmsg_type == NLMSG_DONE) {
- closeSocketQuietly(fd);
return;
}
if (!msgClass.isInstance(nlMsg)) {
- Log.e(TAG, "Received unexpected netlink message: " + nlMsg);
+ Log.wtf(TAG, "Received unexpected netlink message: " + nlMsg);
continue;
}
@@ -387,6 +355,32 @@
}
}
}
+ /**
+ * Sends a netlink dump request and processes the returned dump messages
+ *
+ * @param <T> extends NetlinkMessage
+ * @param dumpRequestMessage netlink dump request message to be sent
+ * @param nlFamily netlink family
+ * @param msgClass expected class of the netlink message
+ * @param func function defined by caller to handle the dump messages
+ * @throws SocketException when fails to connect socket to kernel
+ * @throws InterruptedIOException when fails to read the dumpFd
+ * @throws ErrnoException when fails to create dump fd, send dump request
+ * or receive messages
+ */
+ public static <T extends NetlinkMessage> void getAndProcessNetlinkDumpMessages(
+ byte[] dumpRequestMessage, int nlFamily, Class<T> msgClass,
+ Consumer<T> func)
+ throws SocketException, InterruptedIOException, ErrnoException {
+ // Create socket
+ final FileDescriptor fd = netlinkSocketForProto(nlFamily);
+ try {
+ getAndProcessNetlinkDumpMessagesWithFd(fd, dumpRequestMessage, nlFamily,
+ msgClass, func);
+ } finally {
+ closeSocketQuietly(fd);
+ }
+ }
/**
* Construct a RTM_GETROUTE message for dumping multicast IPv6 routes from kernel.
@@ -439,7 +433,7 @@
NetlinkUtils.<RtNetlinkRouteMessage>getAndProcessNetlinkDumpMessages(
dumpMsg, NETLINK_ROUTE, RtNetlinkRouteMessage.class,
handleNlDumpMsg);
- } catch (SocketException | InterruptedIOException | ErrnoException | ParseException e) {
+ } catch (SocketException | InterruptedIOException | ErrnoException e) {
Log.e(TAG, "Failed to dump multicast routes");
return routes;
}