summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/moduleutils/Android.bp1
-rw-r--r--common/moduleutils/src/android/net/ip/IpNeighborMonitor.java87
-rw-r--r--common/moduleutils/src/android/net/ip/NetlinkMonitor.java141
3 files changed, 149 insertions, 80 deletions
diff --git a/common/moduleutils/Android.bp b/common/moduleutils/Android.bp
index f32f8d8..93ee00c 100644
--- a/common/moduleutils/Android.bp
+++ b/common/moduleutils/Android.bp
@@ -53,6 +53,7 @@ filegroup {
srcs: [
"src/android/net/ip/InterfaceController.java",
"src/android/net/ip/IpNeighborMonitor.java",
+ "src/android/net/ip/NetlinkMonitor.java",
"src/android/net/netlink/*.java",
"src/android/net/shared/NetdUtils.java",
"src/android/net/shared/RouteUtils.java",
diff --git a/common/moduleutils/src/android/net/ip/IpNeighborMonitor.java b/common/moduleutils/src/android/net/ip/IpNeighborMonitor.java
index d6706d4..18a9f90 100644
--- a/common/moduleutils/src/android/net/ip/IpNeighborMonitor.java
+++ b/common/moduleutils/src/android/net/ip/IpNeighborMonitor.java
@@ -19,35 +19,20 @@ package android.net.ip;
import static android.net.netlink.NetlinkConstants.RTM_DELNEIGH;
import static android.net.netlink.NetlinkConstants.hexify;
import static android.net.netlink.NetlinkConstants.stringForNlMsgType;
-import static android.net.util.SocketUtils.makeNetlinkSocketAddress;
-import static android.system.OsConstants.AF_NETLINK;
import static android.system.OsConstants.NETLINK_ROUTE;
-import static android.system.OsConstants.SOCK_DGRAM;
-import static android.system.OsConstants.SOCK_NONBLOCK;
import android.net.MacAddress;
-import android.net.netlink.NetlinkErrorMessage;
import android.net.netlink.NetlinkMessage;
import android.net.netlink.NetlinkSocket;
import android.net.netlink.RtNetlinkNeighborMessage;
import android.net.netlink.StructNdMsg;
-import android.net.util.PacketReader;
import android.net.util.SharedLog;
-import android.net.util.SocketUtils;
import android.os.Handler;
-import android.os.SystemClock;
import android.system.ErrnoException;
-import android.system.Os;
import android.system.OsConstants;
import android.util.Log;
-import java.io.FileDescriptor;
-import java.io.IOException;
import java.net.InetAddress;
-import java.net.SocketAddress;
-import java.net.SocketException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
import java.util.StringJoiner;
@@ -61,7 +46,7 @@ import java.util.StringJoiner;
*
* @hide
*/
-public class IpNeighborMonitor extends PacketReader {
+public class IpNeighborMonitor extends NetlinkMonitor {
private static final String TAG = IpNeighborMonitor.class.getSimpleName();
private static final boolean DBG = false;
private static final boolean VDBG = false;
@@ -129,85 +114,27 @@ public class IpNeighborMonitor extends PacketReader {
}
}
- // TODO: move NetworkStackUtils.closeSocketQuietly to somewhere accessible to this file.
- private void closeSocketQuietly(FileDescriptor fd) {
- try {
- SocketUtils.closeSocket(fd);
- } catch (IOException ignored) {
- }
- }
-
public interface NeighborEventConsumer {
// Every neighbor event received on the netlink socket is passed in
// here. Subclasses should filter for events of interest.
public void accept(NeighborEvent event);
}
- private final SharedLog mLog;
private final NeighborEventConsumer mConsumer;
public IpNeighborMonitor(Handler h, SharedLog log, NeighborEventConsumer cb) {
- super(h, NetlinkSocket.DEFAULT_RECV_BUFSIZE);
- mLog = log.forSubComponent(TAG);
+ super(h, log, TAG, NETLINK_ROUTE, OsConstants.RTMGRP_NEIGH);
mConsumer = (cb != null) ? cb : (event) -> { /* discard */ };
}
@Override
- protected FileDescriptor createFd() {
- FileDescriptor fd = null;
-
- try {
- fd = Os.socket(AF_NETLINK, SOCK_DGRAM | SOCK_NONBLOCK, NETLINK_ROUTE);
- Os.bind(fd, makeNetlinkSocketAddress(0, OsConstants.RTMGRP_NEIGH));
- NetlinkSocket.connectToKernel(fd);
-
- if (VDBG) {
- final SocketAddress nlAddr = Os.getsockname(fd);
- Log.d(TAG, "bound to sockaddr_nl{" + nlAddr.toString() + "}");
- }
- } catch (ErrnoException|SocketException e) {
- logError("Failed to create rtnetlink socket", e);
- closeSocketQuietly(fd);
- return null;
- }
-
- return fd;
- }
-
- @Override
- protected void handlePacket(byte[] recvbuf, int length) {
- final long whenMs = SystemClock.elapsedRealtime();
-
- final ByteBuffer byteBuffer = ByteBuffer.wrap(recvbuf, 0, length);
- byteBuffer.order(ByteOrder.nativeOrder());
-
- parseNetlinkMessageBuffer(byteBuffer, whenMs);
- }
-
- private void parseNetlinkMessageBuffer(ByteBuffer byteBuffer, long whenMs) {
- while (byteBuffer.remaining() > 0) {
- final int position = byteBuffer.position();
- final NetlinkMessage nlMsg = NetlinkMessage.parse(byteBuffer);
- if (nlMsg == null || nlMsg.getHeader() == null) {
- byteBuffer.position(position);
- mLog.e("unparsable netlink msg: " + hexify(byteBuffer));
- break;
- }
-
- if (nlMsg instanceof NetlinkErrorMessage) {
- mLog.e("netlink error: " + nlMsg);
- continue;
- } else if (!(nlMsg instanceof RtNetlinkNeighborMessage)) {
- mLog.i("non-rtnetlink neighbor msg: " + nlMsg);
- continue;
- }
-
- evaluateRtNetlinkNeighborMessage((RtNetlinkNeighborMessage) nlMsg, whenMs);
+ public void processNetlinkMessage(NetlinkMessage nlMsg, final long whenMs) {
+ if (!(nlMsg instanceof RtNetlinkNeighborMessage)) {
+ mLog.e("non-rtnetlink neighbor msg: " + nlMsg);
+ return;
}
- }
- private void evaluateRtNetlinkNeighborMessage(
- RtNetlinkNeighborMessage neighMsg, long whenMs) {
+ final RtNetlinkNeighborMessage neighMsg = (RtNetlinkNeighborMessage) nlMsg;
final short msgType = neighMsg.getHeader().nlmsg_type;
final StructNdMsg ndMsg = neighMsg.getNdHeader();
if (ndMsg == null) {
diff --git a/common/moduleutils/src/android/net/ip/NetlinkMonitor.java b/common/moduleutils/src/android/net/ip/NetlinkMonitor.java
new file mode 100644
index 0000000..806f3ef
--- /dev/null
+++ b/common/moduleutils/src/android/net/ip/NetlinkMonitor.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package android.net.ip;
+
+import static android.net.netlink.NetlinkConstants.hexify;
+import static android.net.util.SocketUtils.makeNetlinkSocketAddress;
+import static android.system.OsConstants.AF_NETLINK;
+import static android.system.OsConstants.SOCK_DGRAM;
+import static android.system.OsConstants.SOCK_NONBLOCK;
+
+import android.annotation.NonNull;
+import android.net.netlink.NetlinkErrorMessage;
+import android.net.netlink.NetlinkMessage;
+import android.net.netlink.NetlinkSocket;
+import android.net.util.PacketReader;
+import android.net.util.SharedLog;
+import android.net.util.SocketUtils;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.util.Log;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * A simple base class to listen for netlink broadcasts.
+ *
+ * Opens a netlink socket of the given family and binds to the specified groups. Polls the socket
+ * from the event loop of the passed-in {@link Handler}, and calls the subclass-defined
+ * {@link #processNetlinkMessage} method on the handler thread for each netlink message that
+ * arrives. Currently ignores all netlink errors.
+ */
+public class NetlinkMonitor extends PacketReader {
+ protected final SharedLog mLog;
+ protected final String mTag;
+ private final int mFamily;
+ private final int mBindGroups;
+
+ private static final boolean DBG = false;
+
+ /**
+ * Constructs a new {@code NetlinkMonitor} instance.
+ *
+ * @param h The Handler on which to poll for messages and on which to call
+ * {@link #processNetlinkMessage}.
+ * @param log A SharedLog to log to.
+ * @param tag The log tag to use for log messages.
+ * @param family the Netlink socket family to, e.g., {@code NETLINK_ROUTE}.
+ * @param bindGroups the netlink groups to bind to.
+ */
+ public NetlinkMonitor(@NonNull Handler h, @NonNull SharedLog log, @NonNull String tag,
+ int family, int bindGroups) {
+ super(h, NetlinkSocket.DEFAULT_RECV_BUFSIZE);
+ mLog = log.forSubComponent(tag);
+ mTag = tag;
+ mFamily = family;
+ mBindGroups = bindGroups;
+ }
+
+ @Override
+ protected FileDescriptor createFd() {
+ FileDescriptor fd = null;
+
+ try {
+ fd = Os.socket(AF_NETLINK, SOCK_DGRAM | SOCK_NONBLOCK, mFamily);
+ Os.bind(fd, makeNetlinkSocketAddress(0, mBindGroups));
+ NetlinkSocket.connectToKernel(fd);
+
+ if (DBG) {
+ final SocketAddress nlAddr = Os.getsockname(fd);
+ Log.d(mTag, "bound to sockaddr_nl{" + nlAddr.toString() + "}");
+ }
+ } catch (ErrnoException | SocketException e) {
+ logError("Failed to create rtnetlink socket", e);
+ closeSocketQuietly(fd);
+ return null;
+ }
+
+ return fd;
+ }
+
+ @Override
+ protected void handlePacket(byte[] recvbuf, int length) {
+ final long whenMs = SystemClock.elapsedRealtime();
+ final ByteBuffer byteBuffer = ByteBuffer.wrap(recvbuf, 0, length);
+ byteBuffer.order(ByteOrder.nativeOrder());
+
+ while (byteBuffer.remaining() > 0) {
+ final int position = byteBuffer.position();
+ final NetlinkMessage nlMsg = NetlinkMessage.parse(byteBuffer);
+ if (nlMsg == null || nlMsg.getHeader() == null) {
+ byteBuffer.position(position);
+ mLog.e("unparsable netlink msg: " + hexify(byteBuffer));
+ break;
+ }
+
+ if (nlMsg instanceof NetlinkErrorMessage) {
+ mLog.e("netlink error: " + nlMsg);
+ continue;
+ }
+
+ processNetlinkMessage(nlMsg, whenMs);
+ }
+ }
+
+ // TODO: move NetworkStackUtils to frameworks/libs/net for NetworkStackUtils#closeSocketQuietly.
+ private void closeSocketQuietly(FileDescriptor fd) {
+ try {
+ SocketUtils.closeSocket(fd);
+ } catch (IOException ignored) {
+ }
+ }
+
+ /**
+ * Processes one netlink message. Must be overridden by subclasses.
+ * @param nlMsg the message to process.
+ * @param whenMs the timestamp, as measured by {@link SystemClock#elapsedRealtime}, when the
+ * message was received.
+ */
+ protected void processNetlinkMessage(NetlinkMessage nlMsg, long whenMs) { }
+}