diff options
| -rw-r--r-- | api/system-current.txt | 11 | ||||
| -rw-r--r-- | core/java/android/net/util/SocketUtils.java | 74 | ||||
| -rw-r--r-- | packages/NetworkStack/src/android/net/dhcp/DhcpServer.java | 8 | ||||
| -rw-r--r-- | services/net/java/android/net/apf/ApfFilter.java | 5 | ||||
| -rw-r--r-- | services/net/java/android/net/dhcp/DhcpClient.java | 14 | ||||
| -rw-r--r-- | services/net/java/android/net/ip/ConnectivityPacketTracker.java | 4 | ||||
| -rw-r--r-- | services/net/java/android/net/ip/IpNeighborMonitor.java | 13 | ||||
| -rw-r--r-- | services/net/java/android/net/netlink/NetlinkSocket.java | 10 |
8 files changed, 109 insertions, 30 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index 74ca75c48398..d1df1a52ae12 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4238,6 +4238,17 @@ package android.net.metrics { } +package android.net.util { + + public class SocketUtils { + method public static void bindSocketToInterface(java.io.FileDescriptor, String) throws android.system.ErrnoException; + method public static java.net.SocketAddress makeNetlinkSocketAddress(int, int); + method public static java.net.SocketAddress makePacketSocketAddress(short, int); + method public static java.net.SocketAddress makePacketSocketAddress(int, byte[]); + } + +} + package android.net.wifi { public abstract class EasyConnectStatusCallback { diff --git a/core/java/android/net/util/SocketUtils.java b/core/java/android/net/util/SocketUtils.java new file mode 100644 index 000000000000..de67cf5952f4 --- /dev/null +++ b/core/java/android/net/util/SocketUtils.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2015 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.util; + +import static android.system.OsConstants.SOL_SOCKET; +import static android.system.OsConstants.SO_BINDTODEVICE; + +import android.annotation.SystemApi; +import android.net.NetworkUtils; +import android.system.ErrnoException; +import android.system.NetlinkSocketAddress; +import android.system.Os; +import android.system.PacketSocketAddress; + +import java.io.FileDescriptor; +import java.net.SocketAddress; + +/** + * Collection of utilities to interact with raw sockets. + * @hide + */ +@SystemApi +public class SocketUtils { + /** + * Create a raw datagram socket that is bound to an interface. + * + * <p>Data sent through the socket will go directly to the underlying network, ignoring VPNs. + */ + public static void bindSocketToInterface(FileDescriptor socket, String iface) + throws ErrnoException { + // SO_BINDTODEVICE actually takes a string. This works because the first member + // of struct ifreq is a NULL-terminated interface name. + // TODO: add a setsockoptString() + Os.setsockoptIfreq(socket, SOL_SOCKET, SO_BINDTODEVICE, iface); + NetworkUtils.protectFromVpn(socket); + } + + /** + * Make a socket address to communicate with netlink. + */ + public static SocketAddress makeNetlinkSocketAddress(int portId, int groupsMask) { + return new NetlinkSocketAddress(portId, groupsMask); + } + + /** + * Make a socket address to bind to packet sockets. + */ + public static SocketAddress makePacketSocketAddress(short protocol, int ifIndex) { + return new PacketSocketAddress(protocol, ifIndex); + } + + /** + * Make a socket address to send raw packets. + */ + public static SocketAddress makePacketSocketAddress(int ifIndex, byte[] hwAddr) { + return new PacketSocketAddress(ifIndex, hwAddr); + } + + private SocketUtils() {} +} diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java b/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java index 14e293694ebd..7b112dfc125c 100644 --- a/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java +++ b/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java @@ -29,7 +29,6 @@ import static android.system.OsConstants.AF_INET; import static android.system.OsConstants.IPPROTO_UDP; import static android.system.OsConstants.SOCK_DGRAM; import static android.system.OsConstants.SOL_SOCKET; -import static android.system.OsConstants.SO_BINDTODEVICE; import static android.system.OsConstants.SO_BROADCAST; import static android.system.OsConstants.SO_REUSEADDR; @@ -45,6 +44,7 @@ import android.net.MacAddress; import android.net.NetworkUtils; import android.net.TrafficStats; import android.net.util.SharedLog; +import android.net.util.SocketUtils; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; @@ -629,14 +629,10 @@ public class DhcpServer extends IDhcpServer.Stub { final int oldTag = TrafficStats.getAndSetThreadStatsTag(TAG_SYSTEM_DHCP_SERVER); try { mSocket = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + SocketUtils.bindSocketToInterface(mSocket, mIfName); Os.setsockoptInt(mSocket, SOL_SOCKET, SO_REUSEADDR, 1); - // SO_BINDTODEVICE actually takes a string. This works because the first member - // of struct ifreq is a NULL-terminated interface name. - // TODO: add a setsockoptString() - Os.setsockoptIfreq(mSocket, SOL_SOCKET, SO_BINDTODEVICE, mIfName); Os.setsockoptInt(mSocket, SOL_SOCKET, SO_BROADCAST, 1); Os.bind(mSocket, Inet4Address.ANY, DHCP_SERVER); - NetworkUtils.protectFromVpn(mSocket); return mSocket; } catch (IOException | ErrnoException e) { diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java index 3351b25d0eec..494395285f5b 100644 --- a/services/net/java/android/net/apf/ApfFilter.java +++ b/services/net/java/android/net/apf/ApfFilter.java @@ -20,6 +20,7 @@ import static android.net.util.NetworkConstants.ICMPV6_ECHO_REQUEST_TYPE; import static android.net.util.NetworkConstants.ICMPV6_NEIGHBOR_ADVERTISEMENT; import static android.net.util.NetworkConstants.ICMPV6_ROUTER_ADVERTISEMENT; import static android.net.util.NetworkConstants.ICMPV6_ROUTER_SOLICITATION; +import static android.net.util.SocketUtils.makePacketSocketAddress; import static android.system.OsConstants.AF_PACKET; import static android.system.OsConstants.ARPHRD_ETHER; import static android.system.OsConstants.ETH_P_ARP; @@ -55,7 +56,6 @@ import android.os.PowerManager; import android.os.SystemClock; import android.system.ErrnoException; import android.system.Os; -import android.system.PacketSocketAddress; import android.text.format.DateUtils; import android.util.Log; import android.util.Pair; @@ -72,6 +72,7 @@ import java.io.IOException; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; +import java.net.SocketAddress; import java.net.SocketException; import java.net.UnknownHostException; import java.nio.BufferUnderflowException; @@ -472,7 +473,7 @@ public class ApfFilter { installNewProgramLocked(); } socket = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IPV6); - PacketSocketAddress addr = new PacketSocketAddress( + SocketAddress addr = makePacketSocketAddress( (short) ETH_P_IPV6, mInterfaceParams.index); Os.bind(socket, addr); NetworkUtils.attachRaFilter(socket, mApfCapabilities.apfPacketFormat); diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java index 15acc0ede8b2..733d9a065d45 100644 --- a/services/net/java/android/net/dhcp/DhcpClient.java +++ b/services/net/java/android/net/dhcp/DhcpClient.java @@ -28,6 +28,7 @@ import static android.net.dhcp.DhcpPacket.DHCP_SUBNET_MASK; import static android.net.dhcp.DhcpPacket.DHCP_VENDOR_INFO; import static android.net.dhcp.DhcpPacket.INADDR_ANY; import static android.net.dhcp.DhcpPacket.INADDR_BROADCAST; +import static android.net.util.SocketUtils.makePacketSocketAddress; import static android.system.OsConstants.AF_INET; import static android.system.OsConstants.AF_PACKET; import static android.system.OsConstants.ETH_P_IP; @@ -35,7 +36,6 @@ import static android.system.OsConstants.IPPROTO_UDP; import static android.system.OsConstants.SOCK_DGRAM; import static android.system.OsConstants.SOCK_RAW; import static android.system.OsConstants.SOL_SOCKET; -import static android.system.OsConstants.SO_BINDTODEVICE; import static android.system.OsConstants.SO_BROADCAST; import static android.system.OsConstants.SO_RCVBUF; import static android.system.OsConstants.SO_REUSEADDR; @@ -48,11 +48,11 @@ import android.net.metrics.DhcpClientEvent; import android.net.metrics.DhcpErrorEvent; import android.net.metrics.IpConnectivityLog; import android.net.util.InterfaceParams; +import android.net.util.SocketUtils; import android.os.Message; import android.os.SystemClock; import android.system.ErrnoException; import android.system.Os; -import android.system.PacketSocketAddress; import android.util.EventLog; import android.util.Log; import android.util.SparseArray; @@ -70,6 +70,7 @@ import libcore.io.IoBridge; import java.io.FileDescriptor; import java.io.IOException; import java.net.Inet4Address; +import java.net.SocketAddress; import java.net.SocketException; import java.nio.ByteBuffer; import java.util.Arrays; @@ -204,7 +205,7 @@ public class DhcpClient extends StateMachine { private InterfaceParams mIface; // TODO: MacAddress-ify more of this class hierarchy. private byte[] mHwAddr; - private PacketSocketAddress mInterfaceBroadcastAddr; + private SocketAddress mInterfaceBroadcastAddr; private int mTransactionId; private long mTransactionStartMillis; private DhcpResults mDhcpLease; @@ -293,7 +294,7 @@ public class DhcpClient extends StateMachine { } mHwAddr = mIface.macAddr.toByteArray(); - mInterfaceBroadcastAddr = new PacketSocketAddress(mIface.index, DhcpPacket.ETHER_BROADCAST); + mInterfaceBroadcastAddr = makePacketSocketAddress(mIface.index, DhcpPacket.ETHER_BROADCAST); return true; } @@ -309,7 +310,7 @@ public class DhcpClient extends StateMachine { private boolean initPacketSocket() { try { mPacketSock = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IP); - PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IP, mIface.index); + SocketAddress addr = makePacketSocketAddress((short) ETH_P_IP, mIface.index); Os.bind(mPacketSock, addr); NetworkUtils.attachDhcpFilter(mPacketSock); } catch(SocketException|ErrnoException e) { @@ -323,12 +324,11 @@ public class DhcpClient extends StateMachine { final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_DHCP); try { mUdpSock = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + SocketUtils.bindSocketToInterface(mUdpSock, mIfaceName); Os.setsockoptInt(mUdpSock, SOL_SOCKET, SO_REUSEADDR, 1); - Os.setsockoptIfreq(mUdpSock, SOL_SOCKET, SO_BINDTODEVICE, mIfaceName); Os.setsockoptInt(mUdpSock, SOL_SOCKET, SO_BROADCAST, 1); Os.setsockoptInt(mUdpSock, SOL_SOCKET, SO_RCVBUF, 0); Os.bind(mUdpSock, Inet4Address.ANY, DhcpPacket.DHCP_CLIENT); - NetworkUtils.protectFromVpn(mUdpSock); } catch(SocketException|ErrnoException e) { Log.e(TAG, "Error creating UDP socket", e); return false; diff --git a/services/net/java/android/net/ip/ConnectivityPacketTracker.java b/services/net/java/android/net/ip/ConnectivityPacketTracker.java index bef425a37da4..385dd52e4576 100644 --- a/services/net/java/android/net/ip/ConnectivityPacketTracker.java +++ b/services/net/java/android/net/ip/ConnectivityPacketTracker.java @@ -16,6 +16,7 @@ package android.net.ip; +import static android.net.util.SocketUtils.makePacketSocketAddress; import static android.system.OsConstants.AF_PACKET; import static android.system.OsConstants.ARPHRD_ETHER; import static android.system.OsConstants.ETH_P_ALL; @@ -28,7 +29,6 @@ import android.net.util.PacketReader; import android.os.Handler; import android.system.ErrnoException; import android.system.Os; -import android.system.PacketSocketAddress; import android.text.TextUtils; import android.util.LocalLog; import android.util.Log; @@ -103,7 +103,7 @@ public class ConnectivityPacketTracker { try { s = Os.socket(AF_PACKET, SOCK_RAW, 0); NetworkUtils.attachControlPacketFilter(s, ARPHRD_ETHER); - Os.bind(s, new PacketSocketAddress((short) ETH_P_ALL, mInterface.index)); + Os.bind(s, makePacketSocketAddress((short) ETH_P_ALL, mInterface.index)); } catch (ErrnoException | IOException e) { logError("Failed to create packet tracking socket: ", e); closeFd(s); diff --git a/services/net/java/android/net/ip/IpNeighborMonitor.java b/services/net/java/android/net/ip/IpNeighborMonitor.java index 34bf4b63a883..eb993a4243a9 100644 --- a/services/net/java/android/net/ip/IpNeighborMonitor.java +++ b/services/net/java/android/net/ip/IpNeighborMonitor.java @@ -19,6 +19,7 @@ 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 android.net.MacAddress; import android.net.netlink.NetlinkErrorMessage; @@ -31,7 +32,6 @@ import android.net.util.SharedLog; import android.os.Handler; import android.os.SystemClock; import android.system.ErrnoException; -import android.system.NetlinkSocketAddress; import android.system.Os; import android.system.OsConstants; import android.util.Log; @@ -148,15 +148,12 @@ public class IpNeighborMonitor extends PacketReader { try { fd = NetlinkSocket.forProto(OsConstants.NETLINK_ROUTE); - Os.bind(fd, (SocketAddress)(new NetlinkSocketAddress(0, OsConstants.RTMGRP_NEIGH))); - Os.connect(fd, (SocketAddress)(new NetlinkSocketAddress(0, 0))); + Os.bind(fd, makeNetlinkSocketAddress(0, OsConstants.RTMGRP_NEIGH)); + NetlinkSocket.connectToKernel(fd); if (VDBG) { - final NetlinkSocketAddress nlAddr = (NetlinkSocketAddress) Os.getsockname(fd); - Log.d(TAG, "bound to sockaddr_nl{" - + BitUtils.uint32(nlAddr.getPortId()) + ", " - + nlAddr.getGroupsMask() - + "}"); + 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); diff --git a/services/net/java/android/net/netlink/NetlinkSocket.java b/services/net/java/android/net/netlink/NetlinkSocket.java index 40098c1532b1..2a98d90e5577 100644 --- a/services/net/java/android/net/netlink/NetlinkSocket.java +++ b/services/net/java/android/net/netlink/NetlinkSocket.java @@ -16,26 +16,26 @@ package android.net.netlink; +import static android.net.util.SocketUtils.makeNetlinkSocketAddress; import static android.system.OsConstants.AF_NETLINK; import static android.system.OsConstants.EIO; import static android.system.OsConstants.EPROTO; import static android.system.OsConstants.ETIMEDOUT; +import static android.system.OsConstants.SOCK_DGRAM; +import static android.system.OsConstants.SOL_SOCKET; import static android.system.OsConstants.SO_RCVBUF; import static android.system.OsConstants.SO_RCVTIMEO; import static android.system.OsConstants.SO_SNDTIMEO; -import static android.system.OsConstants.SOCK_DGRAM; -import static android.system.OsConstants.SOL_SOCKET; import android.system.ErrnoException; -import android.system.NetlinkSocketAddress; import android.system.Os; import android.system.StructTimeval; import android.util.Log; + import libcore.io.IoUtils; import java.io.FileDescriptor; import java.io.InterruptedIOException; -import java.net.SocketAddress; import java.net.SocketException; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -106,7 +106,7 @@ public class NetlinkSocket { } public static void connectToKernel(FileDescriptor fd) throws ErrnoException, SocketException { - Os.connect(fd, (SocketAddress) (new NetlinkSocketAddress(0, 0))); + Os.connect(fd, makeNetlinkSocketAddress(0, 0)); } private static void checkTimeout(long timeoutMs) { |