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 4f76577caac2e63e268eb460c9466e3af3e80a76..c6a204298d58ddfc05e1bb246af4fc6ffcc56eb1 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.ByteBuffer; 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 @@ public class InetDiagMessage extends NetlinkMessage { 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 @@ public class InetDiagMessage extends NetlinkMessage { 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 @@ public class InetDiagMessage extends NetlinkMessage { 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 fafa5eeef73f2b9a47161ef1b356ab96c0ebb0c8..7c2be2cfbed972b19b29e59028a630ea168d7218 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.NetlinkConstants.RTNL_FAMILY_I 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 @@ public class NetlinkUtils { 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(); - } - - try { - connectToKernel(fd); - } catch (ErrnoException | SocketException e) { - Log.e(TAG, "Failed to connect netlink socket to kernel " + e); - closeSocketQuietly(fd); - return; - } + throws SocketException, InterruptedIOException, ErrnoException { + // connecToKernel throws ErrnoException and SocketException, should be handled by caller + connectToKernel(fd); - 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 @@ public class NetlinkUtils { // 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 @@ public class 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 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 @@ public class NetlinkUtils { 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; }