From 51038e8b3c102e23a01d48794fccaed4f7c900e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruoyao=20Liu=20=28=E5=88=98=E8=8B=A5=E5=B0=A7=29?= Date: Mon, 20 May 2019 11:22:22 +0800 Subject: [PATCH] Add API to set the sll_protocol on PacketSocket Problem & Root cause: the mInterfaceBroadcastAddr.sll_protocol is not assigned when the interface initializes, sll_protocol is 0x0000 by default. This causes packets to be filtered incorrectly in packet capture, typically with tcpdump. The previous API is used by DhcpClient, causing DHCP tx messages to not be recognized properly. Background: inside the kernel packets carry both an ethertype metadata (skb->protocol) and may also carry a real ethertype in the mac header. Previously skb->protocol would be inherited from the socket either from the protocol from socket() creation or from bind(). This was zero, so skb->protocol would end up 0, even though the DHCP packets we actually wrote would have the right on-the-wire ethertype populated in the bytes passed to send(). As such DHCP packets would look correctly on the wire, but were lacking the skb->protocol metadata to correctly tag them as IPv4. This results in 'tc' and packet hooks potentially not triggering correctly, and can thus result in tcpdump 'ipv4' filters discarding these packets leading to confusing/erroneous tcpdump output. In newer kernels (somewhere around 5.3), if socket protocol is 0, we actually parse out the right ethertype from the mac header during send(). However, for old kernels we can't rely on this kernel magic, and the right fix is simply to make sure that socket bound protocol is correctly set to ipv4 [htons(ETH_P_IP)] in the bind() system call. Solution: Add a new constructor in SocketUtils to set the protocol parameter. Bug: 133196453 Test: manual test Change-Id: I07887b82e0e32aadb0cbb9f930f2b2fa3e277ca9 --- api/system-current.txt | 3 ++- api/test-current.txt | 3 ++- core/java/android/net/util/SocketUtils.java | 14 ++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/api/system-current.txt b/api/system-current.txt index a9d228971d22d..26ee7588ad7ac 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4432,7 +4432,8 @@ package android.net.util { method public static void closeSocket(@Nullable java.io.FileDescriptor) throws java.io.IOException; method @NonNull public static java.net.SocketAddress makeNetlinkSocketAddress(int, int); method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int); - method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]); + method @Deprecated @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]); + method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int, @NonNull byte[]); } } diff --git a/api/test-current.txt b/api/test-current.txt index 716f0c68dbc3e..349aeb1c1e3a1 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -1654,7 +1654,8 @@ package android.net.util { method public static void closeSocket(@Nullable java.io.FileDescriptor) throws java.io.IOException; method @NonNull public static java.net.SocketAddress makeNetlinkSocketAddress(int, int); method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int); - method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]); + method @Deprecated @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]); + method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int, @NonNull byte[]); } } diff --git a/core/java/android/net/util/SocketUtils.java b/core/java/android/net/util/SocketUtils.java index 489a2922f70e3..e9ea99f84f905 100644 --- a/core/java/android/net/util/SocketUtils.java +++ b/core/java/android/net/util/SocketUtils.java @@ -77,7 +77,9 @@ public final class SocketUtils { /** * Make a socket address that packet socket can send packets to. + * @deprecated Use {@link #makePacketSocketAddress(int, int, byte[])} instead. */ + @Deprecated @NonNull public static SocketAddress makePacketSocketAddress(int ifIndex, @NonNull byte[] hwAddr) { return new PacketSocketAddress( @@ -86,6 +88,18 @@ public final class SocketUtils { hwAddr /* sll_addr */); } + /** + * Make a socket address that packet socket can send packets to. + */ + @NonNull + public static SocketAddress makePacketSocketAddress(int protocol, int ifIndex, + @NonNull byte[] hwAddr) { + return new PacketSocketAddress( + protocol /* sll_protocol */, + ifIndex /* sll_ifindex */, + hwAddr /* sll_addr */); + } + /** * @see IoBridge#closeAndSignalBlockedThreads(FileDescriptor) */