Loading common/moduleutils/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ filegroup { filegroup { name: "tethering-module-utils-srcs", srcs: [ "src/android/net/ip/ConntrackMonitor.java", "src/android/net/ip/InterfaceController.java", "src/android/net/ip/IpNeighborMonitor.java", "src/android/net/ip/NetlinkMonitor.java", Loading common/moduleutils/src/android/net/ip/ConntrackMonitor.java 0 → 100644 +79 −0 Original line number Diff line number Diff line /* * 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 android.net.netlink.ConntrackMessage; import android.net.netlink.NetlinkMessage; import android.net.util.SharedLog; import android.os.Handler; import android.system.OsConstants; import androidx.annotation.NonNull; /** * ConntrackMonitor. * * Monitors the netfilter conntrack notifications and presents to callers * ConntrackEvents describing each event. * * @hide */ public class ConntrackMonitor extends NetlinkMonitor { private static final String TAG = ConntrackMonitor.class.getSimpleName(); private static final boolean DBG = false; private static final boolean VDBG = false; // Reference kernel/uapi/linux/netfilter/nfnetlink_compat.h public static final int NF_NETLINK_CONNTRACK_NEW = 1; public static final int NF_NETLINK_CONNTRACK_UPDATE = 2; public static final int NF_NETLINK_CONNTRACK_DESTROY = 4; /** * A class for describing parsed netfilter conntrack events. */ public static class ConntrackEvent { /*TODO*/ } /** * A callback to caller for conntrack event. */ public interface ConntrackEventConsumer { /** * Every conntrack event received on the netlink socket is passed in * here. */ void accept(@NonNull ConntrackEvent event); } private final ConntrackEventConsumer mConsumer; public ConntrackMonitor(@NonNull Handler h, @NonNull SharedLog log, @NonNull ConntrackEventConsumer cb) { super(h, log, TAG, OsConstants.NETLINK_NETFILTER, NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY); mConsumer = cb; } @Override public void processNetlinkMessage(NetlinkMessage nlMsg, final long whenMs) { if (!(nlMsg instanceof ConntrackMessage)) { mLog.e("non-conntrack msg: " + nlMsg); return; } mConsumer.accept(new ConntrackEvent() /* TODO */); } } common/netlinkclient/src/android/net/netlink/ConntrackMessage.java +23 −4 Original line number Diff line number Diff line Loading @@ -39,9 +39,6 @@ import java.nio.ByteOrder; public class ConntrackMessage extends NetlinkMessage { public static final int STRUCT_SIZE = StructNlMsgHdr.STRUCT_SIZE + StructNfGenMsg.STRUCT_SIZE; public static final short NFNL_SUBSYS_CTNETLINK = 1; public static final short IPCTNL_MSG_CT_NEW = 0; // enum ctattr_type public static final short CTA_TUPLE_ORIG = 1; public static final short CTA_TUPLE_REPLY = 2; Loading Loading @@ -84,7 +81,8 @@ public class ConntrackMessage extends NetlinkMessage { final ConntrackMessage ctmsg = new ConntrackMessage(); ctmsg.mHeader.nlmsg_len = bytes.length; ctmsg.mHeader.nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_NEW; ctmsg.mHeader.nlmsg_type = (NetlinkConstants.NFNL_SUBSYS_CTNETLINK << 8) | NetlinkConstants.IPCTNL_MSG_CT_NEW; ctmsg.mHeader.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE; ctmsg.mHeader.nlmsg_seq = 1; ctmsg.pack(byteBuffer); Loading @@ -95,6 +93,22 @@ public class ConntrackMessage extends NetlinkMessage { return bytes; } /** * Parses a netfilter conntrack message from a {@link ByteBuffer}. * * @param header the netlink message header. * @param byteBuffer The buffer from which to parse the netfilter conntrack message. * @return the parsed netfilter conntrack message, or {@code null} if the netfilter conntrack * message could not be parsed successfully (for example, if it was truncated). */ public static ConntrackMessage parse(StructNlMsgHdr header, ByteBuffer byteBuffer) { // Just build the netlink header for now and pretend the whole message was consumed. // TODO: Parse the netfilter message header and conntrack attributes. final ConntrackMessage conntrackMsg = new ConntrackMessage(header); byteBuffer.position(byteBuffer.limit()); return conntrackMsg; } protected StructNfGenMsg mNfGenMsg; private ConntrackMessage() { Loading @@ -102,6 +116,11 @@ public class ConntrackMessage extends NetlinkMessage { mNfGenMsg = new StructNfGenMsg((byte) OsConstants.AF_INET); } private ConntrackMessage(StructNlMsgHdr header) { super(header); mNfGenMsg = null; } public void pack(ByteBuffer byteBuffer) { mHeader.pack(byteBuffer); mNfGenMsg.pack(byteBuffer); Loading common/netlinkclient/src/android/net/netlink/NetlinkConstants.java +68 −27 Original line number Diff line number Diff line Loading @@ -27,8 +27,10 @@ import java.nio.ByteBuffer; * * Values taken from: * * <linux_src>/include/uapi/linux/netlink.h * <linux_src>/include/uapi/linux/rtnetlink.h * include/uapi/linux/netfilter/nfnetlink.h * include/uapi/linux/netfilter/nfnetlink_conntrack.h * include/uapi/linux/netlink.h * include/uapi/linux/rtnetlink.h * * @hide */ Loading Loading @@ -104,7 +106,21 @@ public class NetlinkConstants { public static final short RTM_GETRULE = 34; public static final short RTM_NEWNDUSEROPT = 68; /* see <linux_src>/include/uapi/linux/sock_diag.h */ // Netfilter netlink message types are presented by two bytes: high byte subsystem and // low byte operation. See the macro NFNL_SUBSYS_ID and NFNL_MSG_TYPE in // include/uapi/linux/netfilter/nfnetlink.h public static final short NFNL_SUBSYS_CTNETLINK = 1; public static final short IPCTNL_MSG_CT_NEW = 0; public static final short IPCTNL_MSG_CT_GET = 1; public static final short IPCTNL_MSG_CT_DELETE = 2; public static final short IPCTNL_MSG_CT_GET_CTRZERO = 3; public static final short IPCTNL_MSG_CT_GET_STATS_CPU = 4; public static final short IPCTNL_MSG_CT_GET_STATS = 5; public static final short IPCTNL_MSG_CT_GET_DYING = 6; public static final short IPCTNL_MSG_CT_GET_UNCONFIRMED = 7; /* see include/uapi/linux/sock_diag.h */ public static final short SOCK_DIAG_BY_FAMILY = 20; // Netlink groups. Loading Loading @@ -163,6 +179,30 @@ public class NetlinkConstants { } } /** * Convert a netlink message type to a string for NETLINK_NETFILTER. */ @NonNull private static String stringForNfMsgType(short nlmType) { final byte subsysId = (byte) (nlmType >> 8); final byte msgType = (byte) nlmType; switch (subsysId) { case NFNL_SUBSYS_CTNETLINK: switch (msgType) { case IPCTNL_MSG_CT_NEW: return "IPCTNL_MSG_CT_NEW"; case IPCTNL_MSG_CT_GET: return "IPCTNL_MSG_CT_GET"; case IPCTNL_MSG_CT_DELETE: return "IPCTNL_MSG_CT_DELETE"; case IPCTNL_MSG_CT_GET_CTRZERO: return "IPCTNL_MSG_CT_GET_CTRZERO"; case IPCTNL_MSG_CT_GET_STATS_CPU: return "IPCTNL_MSG_CT_GET_STATS_CPU"; case IPCTNL_MSG_CT_GET_STATS: return "IPCTNL_MSG_CT_GET_STATS"; case IPCTNL_MSG_CT_GET_DYING: return "IPCTNL_MSG_CT_GET_DYING"; case IPCTNL_MSG_CT_GET_UNCONFIRMED: return "IPCTNL_MSG_CT_GET_UNCONFIRMED"; } break; } return "unknown NETFILTER type: " + String.valueOf(nlmType); } /** * Convert a netlink message type to a string by netlink family. */ Loading @@ -177,6 +217,7 @@ public class NetlinkConstants { // not constant. if (nlFamily == OsConstants.NETLINK_ROUTE) return stringForRtMsgType(nlmType); if (nlFamily == OsConstants.NETLINK_INET_DIAG) return stringForInetDiagMsgType(nlmType); if (nlFamily == OsConstants.NETLINK_NETFILTER) return stringForNfMsgType(nlmType); return "unknown type: " + String.valueOf(nlmType); } Loading common/netlinkclient/src/android/net/netlink/NetlinkMessage.java +16 −0 Original line number Diff line number Diff line Loading @@ -74,6 +74,9 @@ public class NetlinkMessage { if (nlFamily == OsConstants.NETLINK_INET_DIAG) { return parseInetDiagMessage(nlmsghdr, byteBuffer); } if (nlFamily == OsConstants.NETLINK_NETFILTER) { return parseNfMessage(nlmsghdr, byteBuffer); } return null; } Loading Loading @@ -136,4 +139,17 @@ public class NetlinkMessage { default: return null; } } @Nullable private static NetlinkMessage parseNfMessage(@NonNull StructNlMsgHdr nlmsghdr, @NonNull ByteBuffer byteBuffer) { switch (nlmsghdr.nlmsg_type) { case NetlinkConstants.NFNL_SUBSYS_CTNETLINK << 8 | NetlinkConstants.IPCTNL_MSG_CT_NEW: case NetlinkConstants.NFNL_SUBSYS_CTNETLINK << 8 | NetlinkConstants.IPCTNL_MSG_CT_DELETE: return (NetlinkMessage) ConntrackMessage.parse(nlmsghdr, byteBuffer); default: return null; } } } Loading
common/moduleutils/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ filegroup { filegroup { name: "tethering-module-utils-srcs", srcs: [ "src/android/net/ip/ConntrackMonitor.java", "src/android/net/ip/InterfaceController.java", "src/android/net/ip/IpNeighborMonitor.java", "src/android/net/ip/NetlinkMonitor.java", Loading
common/moduleutils/src/android/net/ip/ConntrackMonitor.java 0 → 100644 +79 −0 Original line number Diff line number Diff line /* * 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 android.net.netlink.ConntrackMessage; import android.net.netlink.NetlinkMessage; import android.net.util.SharedLog; import android.os.Handler; import android.system.OsConstants; import androidx.annotation.NonNull; /** * ConntrackMonitor. * * Monitors the netfilter conntrack notifications and presents to callers * ConntrackEvents describing each event. * * @hide */ public class ConntrackMonitor extends NetlinkMonitor { private static final String TAG = ConntrackMonitor.class.getSimpleName(); private static final boolean DBG = false; private static final boolean VDBG = false; // Reference kernel/uapi/linux/netfilter/nfnetlink_compat.h public static final int NF_NETLINK_CONNTRACK_NEW = 1; public static final int NF_NETLINK_CONNTRACK_UPDATE = 2; public static final int NF_NETLINK_CONNTRACK_DESTROY = 4; /** * A class for describing parsed netfilter conntrack events. */ public static class ConntrackEvent { /*TODO*/ } /** * A callback to caller for conntrack event. */ public interface ConntrackEventConsumer { /** * Every conntrack event received on the netlink socket is passed in * here. */ void accept(@NonNull ConntrackEvent event); } private final ConntrackEventConsumer mConsumer; public ConntrackMonitor(@NonNull Handler h, @NonNull SharedLog log, @NonNull ConntrackEventConsumer cb) { super(h, log, TAG, OsConstants.NETLINK_NETFILTER, NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY); mConsumer = cb; } @Override public void processNetlinkMessage(NetlinkMessage nlMsg, final long whenMs) { if (!(nlMsg instanceof ConntrackMessage)) { mLog.e("non-conntrack msg: " + nlMsg); return; } mConsumer.accept(new ConntrackEvent() /* TODO */); } }
common/netlinkclient/src/android/net/netlink/ConntrackMessage.java +23 −4 Original line number Diff line number Diff line Loading @@ -39,9 +39,6 @@ import java.nio.ByteOrder; public class ConntrackMessage extends NetlinkMessage { public static final int STRUCT_SIZE = StructNlMsgHdr.STRUCT_SIZE + StructNfGenMsg.STRUCT_SIZE; public static final short NFNL_SUBSYS_CTNETLINK = 1; public static final short IPCTNL_MSG_CT_NEW = 0; // enum ctattr_type public static final short CTA_TUPLE_ORIG = 1; public static final short CTA_TUPLE_REPLY = 2; Loading Loading @@ -84,7 +81,8 @@ public class ConntrackMessage extends NetlinkMessage { final ConntrackMessage ctmsg = new ConntrackMessage(); ctmsg.mHeader.nlmsg_len = bytes.length; ctmsg.mHeader.nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_NEW; ctmsg.mHeader.nlmsg_type = (NetlinkConstants.NFNL_SUBSYS_CTNETLINK << 8) | NetlinkConstants.IPCTNL_MSG_CT_NEW; ctmsg.mHeader.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE; ctmsg.mHeader.nlmsg_seq = 1; ctmsg.pack(byteBuffer); Loading @@ -95,6 +93,22 @@ public class ConntrackMessage extends NetlinkMessage { return bytes; } /** * Parses a netfilter conntrack message from a {@link ByteBuffer}. * * @param header the netlink message header. * @param byteBuffer The buffer from which to parse the netfilter conntrack message. * @return the parsed netfilter conntrack message, or {@code null} if the netfilter conntrack * message could not be parsed successfully (for example, if it was truncated). */ public static ConntrackMessage parse(StructNlMsgHdr header, ByteBuffer byteBuffer) { // Just build the netlink header for now and pretend the whole message was consumed. // TODO: Parse the netfilter message header and conntrack attributes. final ConntrackMessage conntrackMsg = new ConntrackMessage(header); byteBuffer.position(byteBuffer.limit()); return conntrackMsg; } protected StructNfGenMsg mNfGenMsg; private ConntrackMessage() { Loading @@ -102,6 +116,11 @@ public class ConntrackMessage extends NetlinkMessage { mNfGenMsg = new StructNfGenMsg((byte) OsConstants.AF_INET); } private ConntrackMessage(StructNlMsgHdr header) { super(header); mNfGenMsg = null; } public void pack(ByteBuffer byteBuffer) { mHeader.pack(byteBuffer); mNfGenMsg.pack(byteBuffer); Loading
common/netlinkclient/src/android/net/netlink/NetlinkConstants.java +68 −27 Original line number Diff line number Diff line Loading @@ -27,8 +27,10 @@ import java.nio.ByteBuffer; * * Values taken from: * * <linux_src>/include/uapi/linux/netlink.h * <linux_src>/include/uapi/linux/rtnetlink.h * include/uapi/linux/netfilter/nfnetlink.h * include/uapi/linux/netfilter/nfnetlink_conntrack.h * include/uapi/linux/netlink.h * include/uapi/linux/rtnetlink.h * * @hide */ Loading Loading @@ -104,7 +106,21 @@ public class NetlinkConstants { public static final short RTM_GETRULE = 34; public static final short RTM_NEWNDUSEROPT = 68; /* see <linux_src>/include/uapi/linux/sock_diag.h */ // Netfilter netlink message types are presented by two bytes: high byte subsystem and // low byte operation. See the macro NFNL_SUBSYS_ID and NFNL_MSG_TYPE in // include/uapi/linux/netfilter/nfnetlink.h public static final short NFNL_SUBSYS_CTNETLINK = 1; public static final short IPCTNL_MSG_CT_NEW = 0; public static final short IPCTNL_MSG_CT_GET = 1; public static final short IPCTNL_MSG_CT_DELETE = 2; public static final short IPCTNL_MSG_CT_GET_CTRZERO = 3; public static final short IPCTNL_MSG_CT_GET_STATS_CPU = 4; public static final short IPCTNL_MSG_CT_GET_STATS = 5; public static final short IPCTNL_MSG_CT_GET_DYING = 6; public static final short IPCTNL_MSG_CT_GET_UNCONFIRMED = 7; /* see include/uapi/linux/sock_diag.h */ public static final short SOCK_DIAG_BY_FAMILY = 20; // Netlink groups. Loading Loading @@ -163,6 +179,30 @@ public class NetlinkConstants { } } /** * Convert a netlink message type to a string for NETLINK_NETFILTER. */ @NonNull private static String stringForNfMsgType(short nlmType) { final byte subsysId = (byte) (nlmType >> 8); final byte msgType = (byte) nlmType; switch (subsysId) { case NFNL_SUBSYS_CTNETLINK: switch (msgType) { case IPCTNL_MSG_CT_NEW: return "IPCTNL_MSG_CT_NEW"; case IPCTNL_MSG_CT_GET: return "IPCTNL_MSG_CT_GET"; case IPCTNL_MSG_CT_DELETE: return "IPCTNL_MSG_CT_DELETE"; case IPCTNL_MSG_CT_GET_CTRZERO: return "IPCTNL_MSG_CT_GET_CTRZERO"; case IPCTNL_MSG_CT_GET_STATS_CPU: return "IPCTNL_MSG_CT_GET_STATS_CPU"; case IPCTNL_MSG_CT_GET_STATS: return "IPCTNL_MSG_CT_GET_STATS"; case IPCTNL_MSG_CT_GET_DYING: return "IPCTNL_MSG_CT_GET_DYING"; case IPCTNL_MSG_CT_GET_UNCONFIRMED: return "IPCTNL_MSG_CT_GET_UNCONFIRMED"; } break; } return "unknown NETFILTER type: " + String.valueOf(nlmType); } /** * Convert a netlink message type to a string by netlink family. */ Loading @@ -177,6 +217,7 @@ public class NetlinkConstants { // not constant. if (nlFamily == OsConstants.NETLINK_ROUTE) return stringForRtMsgType(nlmType); if (nlFamily == OsConstants.NETLINK_INET_DIAG) return stringForInetDiagMsgType(nlmType); if (nlFamily == OsConstants.NETLINK_NETFILTER) return stringForNfMsgType(nlmType); return "unknown type: " + String.valueOf(nlmType); } Loading
common/netlinkclient/src/android/net/netlink/NetlinkMessage.java +16 −0 Original line number Diff line number Diff line Loading @@ -74,6 +74,9 @@ public class NetlinkMessage { if (nlFamily == OsConstants.NETLINK_INET_DIAG) { return parseInetDiagMessage(nlmsghdr, byteBuffer); } if (nlFamily == OsConstants.NETLINK_NETFILTER) { return parseNfMessage(nlmsghdr, byteBuffer); } return null; } Loading Loading @@ -136,4 +139,17 @@ public class NetlinkMessage { default: return null; } } @Nullable private static NetlinkMessage parseNfMessage(@NonNull StructNlMsgHdr nlmsghdr, @NonNull ByteBuffer byteBuffer) { switch (nlmsghdr.nlmsg_type) { case NetlinkConstants.NFNL_SUBSYS_CTNETLINK << 8 | NetlinkConstants.IPCTNL_MSG_CT_NEW: case NetlinkConstants.NFNL_SUBSYS_CTNETLINK << 8 | NetlinkConstants.IPCTNL_MSG_CT_DELETE: return (NetlinkMessage) ConntrackMessage.parse(nlmsghdr, byteBuffer); default: return null; } } }