Merge "Add SystemApi utility for raw sockets."
am: 91c81c13b6
Change-Id: I91392d479ca24cfcc114ca6f9cf349c833f5f9c5
This commit is contained in:
@@ -3337,6 +3337,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 {
|
||||
|
||||
@Deprecated public class RttManager {
|
||||
|
||||
74
core/java/android/net/util/SocketUtils.java
Normal file
74
core/java/android/net/util/SocketUtils.java
Normal file
@@ -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() {}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user