Merge "Refactor to InterfaceParams utility class" am: 6a91687bcd
am: fe83298cd5
Change-Id: Icb708a5ea7c3b41cb9d23885018b088c65ee427b
This commit is contained in:
@@ -30,6 +30,7 @@ import android.net.RouteInfo;
|
|||||||
import android.net.ip.InterfaceController;
|
import android.net.ip.InterfaceController;
|
||||||
import android.net.ip.RouterAdvertisementDaemon;
|
import android.net.ip.RouterAdvertisementDaemon;
|
||||||
import android.net.ip.RouterAdvertisementDaemon.RaParams;
|
import android.net.ip.RouterAdvertisementDaemon.RaParams;
|
||||||
|
import android.net.util.InterfaceParams;
|
||||||
import android.net.util.NetdService;
|
import android.net.util.NetdService;
|
||||||
import android.net.util.SharedLog;
|
import android.net.util.SharedLog;
|
||||||
import android.os.INetworkManagementService;
|
import android.os.INetworkManagementService;
|
||||||
@@ -48,7 +49,6 @@ import com.android.internal.util.StateMachine;
|
|||||||
|
|
||||||
import java.net.Inet6Address;
|
import java.net.Inet6Address;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.NetworkInterface;
|
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -120,8 +120,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
|
|||||||
private int mLastError;
|
private int mLastError;
|
||||||
private int mServingMode;
|
private int mServingMode;
|
||||||
private String mMyUpstreamIfaceName; // may change over time
|
private String mMyUpstreamIfaceName; // may change over time
|
||||||
private NetworkInterface mNetworkInterface;
|
private InterfaceParams mInterfaceParams;
|
||||||
private byte[] mHwAddr;
|
|
||||||
// TODO: De-duplicate this with mLinkProperties above. Currently, these link
|
// TODO: De-duplicate this with mLinkProperties above. Currently, these link
|
||||||
// properties are those selected by the IPv6TetheringCoordinator and relayed
|
// properties are those selected by the IPv6TetheringCoordinator and relayed
|
||||||
// to us. By comparison, mLinkProperties contains the addresses and directly
|
// to us. By comparison, mLinkProperties contains the addresses and directly
|
||||||
@@ -247,31 +246,16 @@ public class TetherInterfaceStateMachine extends StateMachine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean startIPv6() {
|
private boolean startIPv6() {
|
||||||
// TODO: Refactor for testability (perhaps passing an android.system.Os
|
// TODO: Refactor for better testability. This is one of the things
|
||||||
// instance and calling getifaddrs() directly).
|
// that prohibits unittesting IPv6 tethering setup.
|
||||||
try {
|
mInterfaceParams = InterfaceParams.getByName(mIfaceName);
|
||||||
mNetworkInterface = NetworkInterface.getByName(mIfaceName);
|
if (mInterfaceParams == null) {
|
||||||
} catch (SocketException e) {
|
mLog.e("Failed to find InterfaceParams");
|
||||||
mLog.e("Error looking up NetworkInterfaces: " + e);
|
|
||||||
stopIPv6();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (mNetworkInterface == null) {
|
|
||||||
mLog.e("Failed to find NetworkInterface");
|
|
||||||
stopIPv6();
|
stopIPv6();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
mRaDaemon = new RouterAdvertisementDaemon(mInterfaceParams);
|
||||||
mHwAddr = mNetworkInterface.getHardwareAddress();
|
|
||||||
} catch (SocketException e) {
|
|
||||||
mLog.e("Failed to find hardware address: " + e);
|
|
||||||
stopIPv6();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
final int ifindex = mNetworkInterface.getIndex();
|
|
||||||
mRaDaemon = new RouterAdvertisementDaemon(mIfaceName, ifindex, mHwAddr);
|
|
||||||
if (!mRaDaemon.start()) {
|
if (!mRaDaemon.start()) {
|
||||||
stopIPv6();
|
stopIPv6();
|
||||||
return false;
|
return false;
|
||||||
@@ -281,8 +265,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void stopIPv6() {
|
private void stopIPv6() {
|
||||||
mNetworkInterface = null;
|
mInterfaceParams = null;
|
||||||
mHwAddr = null;
|
|
||||||
setRaParams(null);
|
setRaParams(null);
|
||||||
|
|
||||||
if (mRaDaemon != null) {
|
if (mRaDaemon != null) {
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import android.net.metrics.ApfProgramEvent;
|
|||||||
import android.net.metrics.ApfStats;
|
import android.net.metrics.ApfStats;
|
||||||
import android.net.metrics.IpConnectivityLog;
|
import android.net.metrics.IpConnectivityLog;
|
||||||
import android.net.metrics.RaEvent;
|
import android.net.metrics.RaEvent;
|
||||||
|
import android.net.util.InterfaceParams;
|
||||||
import android.system.ErrnoException;
|
import android.system.ErrnoException;
|
||||||
import android.system.Os;
|
import android.system.Os;
|
||||||
import android.system.PacketSocketAddress;
|
import android.system.PacketSocketAddress;
|
||||||
@@ -56,7 +57,6 @@ import java.lang.Thread;
|
|||||||
import java.net.Inet4Address;
|
import java.net.Inet4Address;
|
||||||
import java.net.Inet6Address;
|
import java.net.Inet6Address;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.NetworkInterface;
|
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
@@ -247,7 +247,7 @@ public class ApfFilter {
|
|||||||
|
|
||||||
private final ApfCapabilities mApfCapabilities;
|
private final ApfCapabilities mApfCapabilities;
|
||||||
private final IpClient.Callback mIpClientCallback;
|
private final IpClient.Callback mIpClientCallback;
|
||||||
private final NetworkInterface mNetworkInterface;
|
private final InterfaceParams mInterfaceParams;
|
||||||
private final IpConnectivityLog mMetricsLog;
|
private final IpConnectivityLog mMetricsLog;
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -269,11 +269,11 @@ public class ApfFilter {
|
|||||||
private int mIPv4PrefixLength;
|
private int mIPv4PrefixLength;
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
ApfFilter(ApfConfiguration config, NetworkInterface networkInterface,
|
ApfFilter(ApfConfiguration config, InterfaceParams ifParams,
|
||||||
IpClient.Callback ipClientCallback, IpConnectivityLog log) {
|
IpClient.Callback ipClientCallback, IpConnectivityLog log) {
|
||||||
mApfCapabilities = config.apfCapabilities;
|
mApfCapabilities = config.apfCapabilities;
|
||||||
mIpClientCallback = ipClientCallback;
|
mIpClientCallback = ipClientCallback;
|
||||||
mNetworkInterface = networkInterface;
|
mInterfaceParams = ifParams;
|
||||||
mMulticastFilter = config.multicastFilter;
|
mMulticastFilter = config.multicastFilter;
|
||||||
mDrop802_3Frames = config.ieee802_3Filter;
|
mDrop802_3Frames = config.ieee802_3Filter;
|
||||||
|
|
||||||
@@ -287,7 +287,7 @@ public class ApfFilter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void log(String s) {
|
private void log(String s) {
|
||||||
Log.d(TAG, "(" + mNetworkInterface.getName() + "): " + s);
|
Log.d(TAG, "(" + mInterfaceParams.name + "): " + s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GuardedBy("this")
|
@GuardedBy("this")
|
||||||
@@ -332,14 +332,14 @@ public class ApfFilter {
|
|||||||
void maybeStartFilter() {
|
void maybeStartFilter() {
|
||||||
FileDescriptor socket;
|
FileDescriptor socket;
|
||||||
try {
|
try {
|
||||||
mHardwareAddress = mNetworkInterface.getHardwareAddress();
|
mHardwareAddress = mInterfaceParams.macAddr.toByteArray();
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
// Install basic filters
|
// Install basic filters
|
||||||
installNewProgramLocked();
|
installNewProgramLocked();
|
||||||
}
|
}
|
||||||
socket = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IPV6);
|
socket = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IPV6);
|
||||||
PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IPV6,
|
PacketSocketAddress addr = new PacketSocketAddress(
|
||||||
mNetworkInterface.getIndex());
|
(short) ETH_P_IPV6, mInterfaceParams.index);
|
||||||
Os.bind(socket, addr);
|
Os.bind(socket, addr);
|
||||||
NetworkUtils.attachRaFilter(socket, mApfCapabilities.apfPacketFormat);
|
NetworkUtils.attachRaFilter(socket, mApfCapabilities.apfPacketFormat);
|
||||||
} catch(SocketException|ErrnoException e) {
|
} catch(SocketException|ErrnoException e) {
|
||||||
@@ -1168,10 +1168,10 @@ public class ApfFilter {
|
|||||||
* filtering using APF programs.
|
* filtering using APF programs.
|
||||||
*/
|
*/
|
||||||
public static ApfFilter maybeCreate(ApfConfiguration config,
|
public static ApfFilter maybeCreate(ApfConfiguration config,
|
||||||
NetworkInterface networkInterface, IpClient.Callback ipClientCallback) {
|
InterfaceParams ifParams, IpClient.Callback ipClientCallback) {
|
||||||
if (config == null) return null;
|
if (config == null || ifParams == null) return null;
|
||||||
ApfCapabilities apfCapabilities = config.apfCapabilities;
|
ApfCapabilities apfCapabilities = config.apfCapabilities;
|
||||||
if (apfCapabilities == null || networkInterface == null) return null;
|
if (apfCapabilities == null) return null;
|
||||||
if (apfCapabilities.apfVersionSupported == 0) return null;
|
if (apfCapabilities.apfVersionSupported == 0) return null;
|
||||||
if (apfCapabilities.maximumApfProgramSize < 512) {
|
if (apfCapabilities.maximumApfProgramSize < 512) {
|
||||||
Log.e(TAG, "Unacceptably small APF limit: " + apfCapabilities.maximumApfProgramSize);
|
Log.e(TAG, "Unacceptably small APF limit: " + apfCapabilities.maximumApfProgramSize);
|
||||||
@@ -1186,7 +1186,7 @@ public class ApfFilter {
|
|||||||
Log.e(TAG, "Unsupported APF version: " + apfCapabilities.apfVersionSupported);
|
Log.e(TAG, "Unsupported APF version: " + apfCapabilities.apfVersionSupported);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new ApfFilter(config, networkInterface, ipClientCallback, new IpConnectivityLog());
|
return new ApfFilter(config, ifParams, ipClientCallback, new IpConnectivityLog());
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void shutdown() {
|
public synchronized void shutdown() {
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import android.net.TrafficStats;
|
|||||||
import android.net.metrics.IpConnectivityLog;
|
import android.net.metrics.IpConnectivityLog;
|
||||||
import android.net.metrics.DhcpClientEvent;
|
import android.net.metrics.DhcpClientEvent;
|
||||||
import android.net.metrics.DhcpErrorEvent;
|
import android.net.metrics.DhcpErrorEvent;
|
||||||
|
import android.net.util.InterfaceParams;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ServiceManager;
|
import android.os.ServiceManager;
|
||||||
@@ -50,7 +51,6 @@ import java.io.FileDescriptor;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.Thread;
|
import java.lang.Thread;
|
||||||
import java.net.Inet4Address;
|
import java.net.Inet4Address;
|
||||||
import java.net.NetworkInterface;
|
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -187,7 +187,8 @@ public class DhcpClient extends StateMachine {
|
|||||||
private final String mIfaceName;
|
private final String mIfaceName;
|
||||||
|
|
||||||
private boolean mRegisteredForPreDhcpNotification;
|
private boolean mRegisteredForPreDhcpNotification;
|
||||||
private NetworkInterface mIface;
|
private InterfaceParams mIface;
|
||||||
|
// TODO: MacAddress-ify more of this class hierarchy.
|
||||||
private byte[] mHwAddr;
|
private byte[] mHwAddr;
|
||||||
private PacketSocketAddress mInterfaceBroadcastAddr;
|
private PacketSocketAddress mInterfaceBroadcastAddr;
|
||||||
private int mTransactionId;
|
private int mTransactionId;
|
||||||
@@ -221,6 +222,7 @@ public class DhcpClient extends StateMachine {
|
|||||||
return new WakeupMessage(mContext, getHandler(), cmdName, cmd);
|
return new WakeupMessage(mContext, getHandler(), cmdName, cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Take an InterfaceParams instance instead of an interface name String.
|
||||||
private DhcpClient(Context context, StateMachine controller, String iface) {
|
private DhcpClient(Context context, StateMachine controller, String iface) {
|
||||||
super(TAG);
|
super(TAG);
|
||||||
|
|
||||||
@@ -262,23 +264,23 @@ public class DhcpClient extends StateMachine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static DhcpClient makeDhcpClient(
|
public static DhcpClient makeDhcpClient(
|
||||||
Context context, StateMachine controller, String intf) {
|
Context context, StateMachine controller, InterfaceParams ifParams) {
|
||||||
DhcpClient client = new DhcpClient(context, controller, intf);
|
DhcpClient client = new DhcpClient(context, controller, ifParams.name);
|
||||||
|
client.mIface = ifParams;
|
||||||
client.start();
|
client.start();
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean initInterface() {
|
private boolean initInterface() {
|
||||||
try {
|
if (mIface == null) mIface = InterfaceParams.getByName(mIfaceName);
|
||||||
mIface = NetworkInterface.getByName(mIfaceName);
|
if (mIface == null) {
|
||||||
mHwAddr = mIface.getHardwareAddress();
|
Log.e(TAG, "Can't determine InterfaceParams for " + mIfaceName);
|
||||||
mInterfaceBroadcastAddr = new PacketSocketAddress(mIface.getIndex(),
|
|
||||||
DhcpPacket.ETHER_BROADCAST);
|
|
||||||
return true;
|
|
||||||
} catch(SocketException | NullPointerException e) {
|
|
||||||
Log.e(TAG, "Can't determine ifindex or MAC address for " + mIfaceName, e);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mHwAddr = mIface.macAddr.toByteArray();
|
||||||
|
mInterfaceBroadcastAddr = new PacketSocketAddress(mIface.index, DhcpPacket.ETHER_BROADCAST);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startNewTransaction() {
|
private void startNewTransaction() {
|
||||||
@@ -293,7 +295,7 @@ public class DhcpClient extends StateMachine {
|
|||||||
private boolean initPacketSocket() {
|
private boolean initPacketSocket() {
|
||||||
try {
|
try {
|
||||||
mPacketSock = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IP);
|
mPacketSock = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IP);
|
||||||
PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IP, mIface.getIndex());
|
PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IP, mIface.index);
|
||||||
Os.bind(mPacketSock, addr);
|
Os.bind(mPacketSock, addr);
|
||||||
NetworkUtils.attachDhcpFilter(mPacketSock);
|
NetworkUtils.attachDhcpFilter(mPacketSock);
|
||||||
} catch(SocketException|ErrnoException e) {
|
} catch(SocketException|ErrnoException e) {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import static android.system.OsConstants.*;
|
|||||||
import android.net.NetworkUtils;
|
import android.net.NetworkUtils;
|
||||||
import android.net.util.PacketReader;
|
import android.net.util.PacketReader;
|
||||||
import android.net.util.ConnectivityPacketSummary;
|
import android.net.util.ConnectivityPacketSummary;
|
||||||
|
import android.net.util.InterfaceParams;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.system.ErrnoException;
|
import android.system.ErrnoException;
|
||||||
import android.system.Os;
|
import android.system.Os;
|
||||||
@@ -35,7 +36,6 @@ import libcore.util.HexEncoding;
|
|||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.io.InterruptedIOException;
|
import java.io.InterruptedIOException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.NetworkInterface;
|
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
|
|
||||||
|
|
||||||
@@ -69,24 +69,12 @@ public class ConnectivityPacketTracker {
|
|||||||
private boolean mRunning;
|
private boolean mRunning;
|
||||||
private String mDisplayName;
|
private String mDisplayName;
|
||||||
|
|
||||||
public ConnectivityPacketTracker(Handler h, NetworkInterface netif, LocalLog log) {
|
public ConnectivityPacketTracker(Handler h, InterfaceParams ifParams, LocalLog log) {
|
||||||
final String ifname;
|
if (ifParams == null) throw new IllegalArgumentException("null InterfaceParams");
|
||||||
final int ifindex;
|
|
||||||
final byte[] hwaddr;
|
|
||||||
final int mtu;
|
|
||||||
|
|
||||||
try {
|
mTag = TAG + "." + ifParams.name;
|
||||||
ifname = netif.getName();
|
|
||||||
ifindex = netif.getIndex();
|
|
||||||
hwaddr = netif.getHardwareAddress();
|
|
||||||
mtu = netif.getMTU();
|
|
||||||
} catch (NullPointerException|SocketException e) {
|
|
||||||
throw new IllegalArgumentException("bad network interface", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
mTag = TAG + "." + ifname;
|
|
||||||
mLog = log;
|
mLog = log;
|
||||||
mPacketListener = new PacketListener(h, ifindex, hwaddr, mtu);
|
mPacketListener = new PacketListener(h, ifParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start(String displayName) {
|
public void start(String displayName) {
|
||||||
@@ -102,13 +90,11 @@ public class ConnectivityPacketTracker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final class PacketListener extends PacketReader {
|
private final class PacketListener extends PacketReader {
|
||||||
private final int mIfIndex;
|
private final InterfaceParams mInterface;
|
||||||
private final byte mHwAddr[];
|
|
||||||
|
|
||||||
PacketListener(Handler h, int ifindex, byte[] hwaddr, int mtu) {
|
PacketListener(Handler h, InterfaceParams ifParams) {
|
||||||
super(h, mtu);
|
super(h, ifParams.defaultMtu);
|
||||||
mIfIndex = ifindex;
|
mInterface = ifParams;
|
||||||
mHwAddr = hwaddr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -117,7 +103,7 @@ public class ConnectivityPacketTracker {
|
|||||||
try {
|
try {
|
||||||
s = Os.socket(AF_PACKET, SOCK_RAW, 0);
|
s = Os.socket(AF_PACKET, SOCK_RAW, 0);
|
||||||
NetworkUtils.attachControlPacketFilter(s, ARPHRD_ETHER);
|
NetworkUtils.attachControlPacketFilter(s, ARPHRD_ETHER);
|
||||||
Os.bind(s, new PacketSocketAddress((short) ETH_P_ALL, mIfIndex));
|
Os.bind(s, new PacketSocketAddress((short) ETH_P_ALL, mInterface.index));
|
||||||
} catch (ErrnoException | IOException e) {
|
} catch (ErrnoException | IOException e) {
|
||||||
logError("Failed to create packet tracking socket: ", e);
|
logError("Failed to create packet tracking socket: ", e);
|
||||||
closeFd(s);
|
closeFd(s);
|
||||||
@@ -129,7 +115,7 @@ public class ConnectivityPacketTracker {
|
|||||||
@Override
|
@Override
|
||||||
protected void handlePacket(byte[] recvbuf, int length) {
|
protected void handlePacket(byte[] recvbuf, int length) {
|
||||||
final String summary = ConnectivityPacketSummary.summarize(
|
final String summary = ConnectivityPacketSummary.summarize(
|
||||||
mHwAddr, recvbuf, length);
|
mInterface.macAddr, recvbuf, length);
|
||||||
if (summary == null) return;
|
if (summary == null) return;
|
||||||
|
|
||||||
if (DBG) Log.d(mTag, summary);
|
if (DBG) Log.d(mTag, summary);
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import android.net.apf.ApfFilter;
|
|||||||
import android.net.dhcp.DhcpClient;
|
import android.net.dhcp.DhcpClient;
|
||||||
import android.net.metrics.IpConnectivityLog;
|
import android.net.metrics.IpConnectivityLog;
|
||||||
import android.net.metrics.IpManagerEvent;
|
import android.net.metrics.IpManagerEvent;
|
||||||
|
import android.net.util.InterfaceParams;
|
||||||
import android.net.util.MultinetworkPolicyTracker;
|
import android.net.util.MultinetworkPolicyTracker;
|
||||||
import android.net.util.NetdService;
|
import android.net.util.NetdService;
|
||||||
import android.net.util.NetworkConstants;
|
import android.net.util.NetworkConstants;
|
||||||
@@ -63,7 +64,6 @@ import java.io.PrintWriter;
|
|||||||
import java.net.Inet4Address;
|
import java.net.Inet4Address;
|
||||||
import java.net.Inet6Address;
|
import java.net.Inet6Address;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.NetworkInterface;
|
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -556,7 +556,7 @@ public class IpClient extends StateMachine {
|
|||||||
private final IpConnectivityLog mMetricsLog = new IpConnectivityLog();
|
private final IpConnectivityLog mMetricsLog = new IpConnectivityLog();
|
||||||
private final InterfaceController mInterfaceCtrl;
|
private final InterfaceController mInterfaceCtrl;
|
||||||
|
|
||||||
private NetworkInterface mNetworkInterface;
|
private InterfaceParams mInterfaceParams;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Non-final member variables accessed only from within our StateMachine.
|
* Non-final member variables accessed only from within our StateMachine.
|
||||||
@@ -722,7 +722,12 @@ public class IpClient extends StateMachine {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
getNetworkInterface();
|
mInterfaceParams = InterfaceParams.getByName(mInterfaceName);
|
||||||
|
if (mInterfaceParams == null) {
|
||||||
|
logError("Failed to find InterfaceParams for " + mInterfaceName);
|
||||||
|
// TODO: call doImmediateProvisioningFailure() with an error code
|
||||||
|
// indicating something like "interface not ready".
|
||||||
|
}
|
||||||
|
|
||||||
mCallback.setNeighborDiscoveryOffload(true);
|
mCallback.setNeighborDiscoveryOffload(true);
|
||||||
sendMessage(CMD_START, new ProvisioningConfiguration(req));
|
sendMessage(CMD_START, new ProvisioningConfiguration(req));
|
||||||
@@ -858,7 +863,7 @@ public class IpClient extends StateMachine {
|
|||||||
protected String getLogRecString(Message msg) {
|
protected String getLogRecString(Message msg) {
|
||||||
final String logLine = String.format(
|
final String logLine = String.format(
|
||||||
"%s/%d %d %d %s [%s]",
|
"%s/%d %d %d %s [%s]",
|
||||||
mInterfaceName, mNetworkInterface == null ? -1 : mNetworkInterface.getIndex(),
|
mInterfaceName, (mInterfaceParams == null) ? -1 : mInterfaceParams.index,
|
||||||
msg.arg1, msg.arg2, Objects.toString(msg.obj), mMsgStateLogger);
|
msg.arg1, msg.arg2, Objects.toString(msg.obj), mMsgStateLogger);
|
||||||
|
|
||||||
final String richerLogLine = getWhatToString(msg.what) + " " + logLine;
|
final String richerLogLine = getWhatToString(msg.what) + " " + logLine;
|
||||||
@@ -889,15 +894,6 @@ public class IpClient extends StateMachine {
|
|||||||
mLog.log(msg);
|
mLog.log(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getNetworkInterface() {
|
|
||||||
try {
|
|
||||||
mNetworkInterface = NetworkInterface.getByName(mInterfaceName);
|
|
||||||
} catch (SocketException | NullPointerException e) {
|
|
||||||
// TODO: throw new IllegalStateException.
|
|
||||||
logError("Failed to get interface object: %s", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This needs to be called with care to ensure that our LinkProperties
|
// This needs to be called with care to ensure that our LinkProperties
|
||||||
// are in sync with the actual LinkProperties of the interface. For example,
|
// are in sync with the actual LinkProperties of the interface. For example,
|
||||||
// we should only call this if we know for sure that there are no IP addresses
|
// we should only call this if we know for sure that there are no IP addresses
|
||||||
@@ -1218,7 +1214,7 @@ public class IpClient extends StateMachine {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Start DHCPv4.
|
// Start DHCPv4.
|
||||||
mDhcpClient = DhcpClient.makeDhcpClient(mContext, IpClient.this, mInterfaceName);
|
mDhcpClient = DhcpClient.makeDhcpClient(mContext, IpClient.this, mInterfaceParams);
|
||||||
mDhcpClient.registerForPreDhcpNotification();
|
mDhcpClient.registerForPreDhcpNotification();
|
||||||
mDhcpClient.sendMessage(DhcpClient.CMD_START_DHCP);
|
mDhcpClient.sendMessage(DhcpClient.CMD_START_DHCP);
|
||||||
}
|
}
|
||||||
@@ -1245,7 +1241,7 @@ public class IpClient extends StateMachine {
|
|||||||
try {
|
try {
|
||||||
mIpReachabilityMonitor = new IpReachabilityMonitor(
|
mIpReachabilityMonitor = new IpReachabilityMonitor(
|
||||||
mContext,
|
mContext,
|
||||||
mInterfaceName,
|
mInterfaceParams,
|
||||||
getHandler(),
|
getHandler(),
|
||||||
mLog,
|
mLog,
|
||||||
new IpReachabilityMonitor.Callback() {
|
new IpReachabilityMonitor.Callback() {
|
||||||
@@ -1447,7 +1443,7 @@ public class IpClient extends StateMachine {
|
|||||||
mContext.getResources().getBoolean(R.bool.config_apfDrop802_3Frames);
|
mContext.getResources().getBoolean(R.bool.config_apfDrop802_3Frames);
|
||||||
apfConfig.ethTypeBlackList =
|
apfConfig.ethTypeBlackList =
|
||||||
mContext.getResources().getIntArray(R.array.config_apfEthTypeBlackList);
|
mContext.getResources().getIntArray(R.array.config_apfEthTypeBlackList);
|
||||||
mApfFilter = ApfFilter.maybeCreate(apfConfig, mNetworkInterface, mCallback);
|
mApfFilter = ApfFilter.maybeCreate(apfConfig, mInterfaceParams, mCallback);
|
||||||
// TODO: investigate the effects of any multicast filtering racing/interfering with the
|
// TODO: investigate the effects of any multicast filtering racing/interfering with the
|
||||||
// rest of this IP configuration startup.
|
// rest of this IP configuration startup.
|
||||||
if (mApfFilter == null) {
|
if (mApfFilter == null) {
|
||||||
@@ -1515,7 +1511,7 @@ public class IpClient extends StateMachine {
|
|||||||
private ConnectivityPacketTracker createPacketTracker() {
|
private ConnectivityPacketTracker createPacketTracker() {
|
||||||
try {
|
try {
|
||||||
return new ConnectivityPacketTracker(
|
return new ConnectivityPacketTracker(
|
||||||
getHandler(), mNetworkInterface, mConnectivityPacketLog);
|
getHandler(), mInterfaceParams, mConnectivityPacketLog);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,11 @@
|
|||||||
|
|
||||||
package android.net.ip;
|
package android.net.ip;
|
||||||
|
|
||||||
import android.net.netlink.NetlinkConstants;
|
import static android.net.netlink.NetlinkConstants.hexify;
|
||||||
|
import static android.net.netlink.NetlinkConstants.RTM_DELNEIGH;
|
||||||
|
import static android.net.netlink.NetlinkConstants.stringForNlMsgType;
|
||||||
|
|
||||||
|
import android.net.MacAddress;
|
||||||
import android.net.netlink.NetlinkErrorMessage;
|
import android.net.netlink.NetlinkErrorMessage;
|
||||||
import android.net.netlink.NetlinkMessage;
|
import android.net.netlink.NetlinkMessage;
|
||||||
import android.net.netlink.NetlinkSocket;
|
import android.net.netlink.NetlinkSocket;
|
||||||
@@ -92,37 +96,35 @@ public class IpNeighborMonitor extends PacketReader {
|
|||||||
final int ifindex;
|
final int ifindex;
|
||||||
final InetAddress ip;
|
final InetAddress ip;
|
||||||
final short nudState;
|
final short nudState;
|
||||||
final byte[] linkLayerAddr;
|
final MacAddress macAddr;
|
||||||
|
|
||||||
public NeighborEvent(long elapsedMs, short msgType, int ifindex, InetAddress ip,
|
public NeighborEvent(long elapsedMs, short msgType, int ifindex, InetAddress ip,
|
||||||
short nudState, byte[] linkLayerAddr) {
|
short nudState, MacAddress macAddr) {
|
||||||
this.elapsedMs = elapsedMs;
|
this.elapsedMs = elapsedMs;
|
||||||
this.msgType = msgType;
|
this.msgType = msgType;
|
||||||
this.ifindex = ifindex;
|
this.ifindex = ifindex;
|
||||||
this.ip = ip;
|
this.ip = ip;
|
||||||
this.nudState = nudState;
|
this.nudState = nudState;
|
||||||
this.linkLayerAddr = linkLayerAddr;
|
this.macAddr = macAddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isConnected() {
|
boolean isConnected() {
|
||||||
return (msgType != NetlinkConstants.RTM_DELNEIGH) &&
|
return (msgType != RTM_DELNEIGH) && StructNdMsg.isNudStateConnected(nudState);
|
||||||
StructNdMsg.isNudStateConnected(nudState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isValid() {
|
boolean isValid() {
|
||||||
return (msgType != NetlinkConstants.RTM_DELNEIGH) &&
|
return (msgType != RTM_DELNEIGH) && StructNdMsg.isNudStateValid(nudState);
|
||||||
StructNdMsg.isNudStateValid(nudState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
final StringJoiner j = new StringJoiner(",", "NeighborEvent{", "}");
|
final StringJoiner j = new StringJoiner(",", "NeighborEvent{", "}");
|
||||||
return j.add("@" + elapsedMs)
|
return j.add("@" + elapsedMs)
|
||||||
.add(NetlinkConstants.stringForNlMsgType(msgType))
|
.add(stringForNlMsgType(msgType))
|
||||||
.add("if=" + ifindex)
|
.add("if=" + ifindex)
|
||||||
.add(ip.getHostAddress())
|
.add(ip.getHostAddress())
|
||||||
.add(StructNdMsg.stringForNudState(nudState))
|
.add(StructNdMsg.stringForNudState(nudState))
|
||||||
.add("[" + NetlinkConstants.hexify(linkLayerAddr) + "]")
|
.add("[" + macAddr + "]")
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -183,7 +185,7 @@ public class IpNeighborMonitor extends PacketReader {
|
|||||||
final NetlinkMessage nlMsg = NetlinkMessage.parse(byteBuffer);
|
final NetlinkMessage nlMsg = NetlinkMessage.parse(byteBuffer);
|
||||||
if (nlMsg == null || nlMsg.getHeader() == null) {
|
if (nlMsg == null || nlMsg.getHeader() == null) {
|
||||||
byteBuffer.position(position);
|
byteBuffer.position(position);
|
||||||
mLog.e("unparsable netlink msg: " + NetlinkConstants.hexify(byteBuffer));
|
mLog.e("unparsable netlink msg: " + hexify(byteBuffer));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,12 +219,13 @@ public class IpNeighborMonitor extends PacketReader {
|
|||||||
final int ifindex = ndMsg.ndm_ifindex;
|
final int ifindex = ndMsg.ndm_ifindex;
|
||||||
final InetAddress destination = neighMsg.getDestination();
|
final InetAddress destination = neighMsg.getDestination();
|
||||||
final short nudState =
|
final short nudState =
|
||||||
(msgType == NetlinkConstants.RTM_DELNEIGH)
|
(msgType == RTM_DELNEIGH)
|
||||||
? StructNdMsg.NUD_NONE
|
? StructNdMsg.NUD_NONE
|
||||||
: ndMsg.ndm_state;
|
: ndMsg.ndm_state;
|
||||||
|
|
||||||
final NeighborEvent event = new NeighborEvent(
|
final NeighborEvent event = new NeighborEvent(
|
||||||
whenMs, msgType, ifindex, destination, nudState, neighMsg.getLinkLayerAddress());
|
whenMs, msgType, ifindex, destination, nudState,
|
||||||
|
getMacAddress(neighMsg.getLinkLayerAddress()));
|
||||||
|
|
||||||
if (VDBG) {
|
if (VDBG) {
|
||||||
Log.d(TAG, neighMsg.toString());
|
Log.d(TAG, neighMsg.toString());
|
||||||
@@ -233,4 +236,16 @@ public class IpNeighborMonitor extends PacketReader {
|
|||||||
|
|
||||||
mConsumer.accept(event);
|
mConsumer.accept(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static MacAddress getMacAddress(byte[] linkLayerAddress) {
|
||||||
|
if (linkLayerAddress != null) {
|
||||||
|
try {
|
||||||
|
return MacAddress.fromBytes(linkLayerAddress);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
Log.e(TAG, "Failed to parse link-layer address: " + hexify(linkLayerAddress));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import android.net.ip.IpNeighborMonitor.NeighborEvent;
|
|||||||
import android.net.metrics.IpConnectivityLog;
|
import android.net.metrics.IpConnectivityLog;
|
||||||
import android.net.metrics.IpReachabilityEvent;
|
import android.net.metrics.IpReachabilityEvent;
|
||||||
import android.net.netlink.StructNdMsg;
|
import android.net.netlink.StructNdMsg;
|
||||||
|
import android.net.util.InterfaceParams;
|
||||||
import android.net.util.MultinetworkPolicyTracker;
|
import android.net.util.MultinetworkPolicyTracker;
|
||||||
import android.net.util.SharedLog;
|
import android.net.util.SharedLog;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@@ -46,9 +47,7 @@ import java.io.PrintWriter;
|
|||||||
import java.net.Inet6Address;
|
import java.net.Inet6Address;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.NetworkInterface;
|
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.net.SocketException;
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -168,8 +167,7 @@ public class IpReachabilityMonitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final String mInterfaceName;
|
private final InterfaceParams mInterfaceParams;
|
||||||
private final int mInterfaceIndex;
|
|
||||||
private final IpNeighborMonitor mIpNeighborMonitor;
|
private final IpNeighborMonitor mIpNeighborMonitor;
|
||||||
private final SharedLog mLog;
|
private final SharedLog mLog;
|
||||||
private final Callback mCallback;
|
private final Callback mCallback;
|
||||||
@@ -182,30 +180,25 @@ public class IpReachabilityMonitor {
|
|||||||
private volatile long mLastProbeTimeMs;
|
private volatile long mLastProbeTimeMs;
|
||||||
|
|
||||||
public IpReachabilityMonitor(
|
public IpReachabilityMonitor(
|
||||||
Context context, String ifName, Handler h, SharedLog log, Callback callback) {
|
Context context, InterfaceParams ifParams, Handler h, SharedLog log, Callback callback,
|
||||||
this(context, ifName, h, log, callback, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IpReachabilityMonitor(
|
|
||||||
Context context, String ifName, Handler h, SharedLog log, Callback callback,
|
|
||||||
MultinetworkPolicyTracker tracker) {
|
MultinetworkPolicyTracker tracker) {
|
||||||
this(ifName, getInterfaceIndex(ifName), h, log, callback, tracker,
|
this(ifParams, h, log, callback, tracker, Dependencies.makeDefault(context, ifParams.name));
|
||||||
Dependencies.makeDefault(context, ifName));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
IpReachabilityMonitor(String ifName, int ifIndex, Handler h, SharedLog log, Callback callback,
|
IpReachabilityMonitor(InterfaceParams ifParams, Handler h, SharedLog log, Callback callback,
|
||||||
MultinetworkPolicyTracker tracker, Dependencies dependencies) {
|
MultinetworkPolicyTracker tracker, Dependencies dependencies) {
|
||||||
mInterfaceName = ifName;
|
if (ifParams == null) throw new IllegalArgumentException("null InterfaceParams");
|
||||||
|
|
||||||
|
mInterfaceParams = ifParams;
|
||||||
mLog = log.forSubComponent(TAG);
|
mLog = log.forSubComponent(TAG);
|
||||||
mCallback = callback;
|
mCallback = callback;
|
||||||
mMultinetworkPolicyTracker = tracker;
|
mMultinetworkPolicyTracker = tracker;
|
||||||
mInterfaceIndex = ifIndex;
|
|
||||||
mDependencies = dependencies;
|
mDependencies = dependencies;
|
||||||
|
|
||||||
mIpNeighborMonitor = new IpNeighborMonitor(h, mLog,
|
mIpNeighborMonitor = new IpNeighborMonitor(h, mLog,
|
||||||
(NeighborEvent event) -> {
|
(NeighborEvent event) -> {
|
||||||
if (mInterfaceIndex != event.ifindex) return;
|
if (mInterfaceParams.index != event.ifindex) return;
|
||||||
if (!mNeighborWatchList.containsKey(event.ip)) return;
|
if (!mNeighborWatchList.containsKey(event.ip)) return;
|
||||||
|
|
||||||
final NeighborEvent prev = mNeighborWatchList.put(event.ip, event);
|
final NeighborEvent prev = mNeighborWatchList.put(event.ip, event);
|
||||||
@@ -241,7 +234,7 @@ public class IpReachabilityMonitor {
|
|||||||
|
|
||||||
private String describeWatchList(String sep) {
|
private String describeWatchList(String sep) {
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
sb.append("iface{" + mInterfaceName + "/" + mInterfaceIndex + "}," + sep);
|
sb.append("iface{" + mInterfaceParams + "}," + sep);
|
||||||
sb.append("ntable=[" + sep);
|
sb.append("ntable=[" + sep);
|
||||||
String delimiter = "";
|
String delimiter = "";
|
||||||
for (Map.Entry<InetAddress, NeighborEvent> entry : mNeighborWatchList.entrySet()) {
|
for (Map.Entry<InetAddress, NeighborEvent> entry : mNeighborWatchList.entrySet()) {
|
||||||
@@ -262,10 +255,10 @@ public class IpReachabilityMonitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void updateLinkProperties(LinkProperties lp) {
|
public void updateLinkProperties(LinkProperties lp) {
|
||||||
if (!mInterfaceName.equals(lp.getInterfaceName())) {
|
if (!mInterfaceParams.name.equals(lp.getInterfaceName())) {
|
||||||
// TODO: figure out whether / how to cope with interface changes.
|
// TODO: figure out whether / how to cope with interface changes.
|
||||||
Log.wtf(TAG, "requested LinkProperties interface '" + lp.getInterfaceName() +
|
Log.wtf(TAG, "requested LinkProperties interface '" + lp.getInterfaceName() +
|
||||||
"' does not match: " + mInterfaceName);
|
"' does not match: " + mInterfaceParams.name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,10 +346,10 @@ public class IpReachabilityMonitor {
|
|||||||
mDependencies.acquireWakeLock(getProbeWakeLockDuration());
|
mDependencies.acquireWakeLock(getProbeWakeLockDuration());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (InetAddress target : ipProbeList) {
|
for (InetAddress ip : ipProbeList) {
|
||||||
final int rval = IpNeighborMonitor.startKernelNeighborProbe(mInterfaceIndex, target);
|
final int rval = IpNeighborMonitor.startKernelNeighborProbe(mInterfaceParams.index, ip);
|
||||||
mLog.log(String.format("put neighbor %s into NUD_PROBE state (rval=%d)",
|
mLog.log(String.format("put neighbor %s into NUD_PROBE state (rval=%d)",
|
||||||
target.getHostAddress(), rval));
|
ip.getHostAddress(), rval));
|
||||||
logEvent(IpReachabilityEvent.PROBE, rval);
|
logEvent(IpReachabilityEvent.PROBE, rval);
|
||||||
}
|
}
|
||||||
mLastProbeTimeMs = SystemClock.elapsedRealtime();
|
mLastProbeTimeMs = SystemClock.elapsedRealtime();
|
||||||
@@ -378,22 +371,9 @@ public class IpReachabilityMonitor {
|
|||||||
return (numUnicastProbes * retransTimeMs) + gracePeriodMs;
|
return (numUnicastProbes * retransTimeMs) + gracePeriodMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getInterfaceIndex(String ifname) {
|
|
||||||
final NetworkInterface iface;
|
|
||||||
try {
|
|
||||||
iface = NetworkInterface.getByName(ifname);
|
|
||||||
} catch (SocketException e) {
|
|
||||||
throw new IllegalArgumentException("invalid interface '" + ifname + "': ", e);
|
|
||||||
}
|
|
||||||
if (iface == null) {
|
|
||||||
throw new IllegalArgumentException("NetworkInterface was null for " + ifname);
|
|
||||||
}
|
|
||||||
return iface.getIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void logEvent(int probeType, int errorCode) {
|
private void logEvent(int probeType, int errorCode) {
|
||||||
int eventType = probeType | (errorCode & 0xff);
|
int eventType = probeType | (errorCode & 0xff);
|
||||||
mMetricsLog.log(mInterfaceName, new IpReachabilityEvent(eventType));
|
mMetricsLog.log(mInterfaceParams.name, new IpReachabilityEvent(eventType));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void logNudFailed(ProvisioningChange delta) {
|
private void logNudFailed(ProvisioningChange delta) {
|
||||||
@@ -401,6 +381,6 @@ public class IpReachabilityMonitor {
|
|||||||
boolean isFromProbe = (duration < getProbeWakeLockDuration());
|
boolean isFromProbe = (duration < getProbeWakeLockDuration());
|
||||||
boolean isProvisioningLost = (delta == ProvisioningChange.LOST_PROVISIONING);
|
boolean isProvisioningLost = (delta == ProvisioningChange.LOST_PROVISIONING);
|
||||||
int eventType = IpReachabilityEvent.nudFailureEventType(isFromProbe, isProvisioningLost);
|
int eventType = IpReachabilityEvent.nudFailureEventType(isFromProbe, isProvisioningLost);
|
||||||
mMetricsLog.log(mInterfaceName, new IpReachabilityEvent(eventType));
|
mMetricsLog.log(mInterfaceParams.name, new IpReachabilityEvent(eventType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import android.net.LinkAddress;
|
|||||||
import android.net.LinkProperties;
|
import android.net.LinkProperties;
|
||||||
import android.net.NetworkUtils;
|
import android.net.NetworkUtils;
|
||||||
import android.net.TrafficStats;
|
import android.net.TrafficStats;
|
||||||
|
import android.net.util.InterfaceParams;
|
||||||
import android.system.ErrnoException;
|
import android.system.ErrnoException;
|
||||||
import android.system.Os;
|
import android.system.Os;
|
||||||
import android.system.StructGroupReq;
|
import android.system.StructGroupReq;
|
||||||
@@ -96,9 +97,7 @@ public class RouterAdvertisementDaemon {
|
|||||||
(byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
|
(byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
|
||||||
};
|
};
|
||||||
|
|
||||||
private final String mIfName;
|
private final InterfaceParams mInterface;
|
||||||
private final int mIfIndex;
|
|
||||||
private final byte[] mHwAddr;
|
|
||||||
private final InetSocketAddress mAllNodes;
|
private final InetSocketAddress mAllNodes;
|
||||||
|
|
||||||
// This lock is to protect the RA from being updated while being
|
// This lock is to protect the RA from being updated while being
|
||||||
@@ -223,11 +222,9 @@ public class RouterAdvertisementDaemon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public RouterAdvertisementDaemon(String ifname, int ifindex, byte[] hwaddr) {
|
public RouterAdvertisementDaemon(InterfaceParams ifParams) {
|
||||||
mIfName = ifname;
|
mInterface = ifParams;
|
||||||
mIfIndex = ifindex;
|
mAllNodes = new InetSocketAddress(getAllNodesForScopeId(mInterface.index), 0);
|
||||||
mHwAddr = hwaddr;
|
|
||||||
mAllNodes = new InetSocketAddress(getAllNodesForScopeId(mIfIndex), 0);
|
|
||||||
mDeprecatedInfoTracker = new DeprecatedInfoTracker();
|
mDeprecatedInfoTracker = new DeprecatedInfoTracker();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,7 +276,7 @@ public class RouterAdvertisementDaemon {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
putHeader(ra, mRaParams != null && mRaParams.hasDefaultRoute);
|
putHeader(ra, mRaParams != null && mRaParams.hasDefaultRoute);
|
||||||
putSlla(ra, mHwAddr);
|
putSlla(ra, mInterface.macAddr.toByteArray());
|
||||||
mRaLength = ra.position();
|
mRaLength = ra.position();
|
||||||
|
|
||||||
// https://tools.ietf.org/html/rfc5175#section-4 says:
|
// https://tools.ietf.org/html/rfc5175#section-4 says:
|
||||||
@@ -579,9 +576,9 @@ public class RouterAdvertisementDaemon {
|
|||||||
// Setting SNDTIMEO is purely for defensive purposes.
|
// Setting SNDTIMEO is purely for defensive purposes.
|
||||||
Os.setsockoptTimeval(
|
Os.setsockoptTimeval(
|
||||||
mSocket, SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(SEND_TIMEOUT_MS));
|
mSocket, SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(SEND_TIMEOUT_MS));
|
||||||
Os.setsockoptIfreq(mSocket, SOL_SOCKET, SO_BINDTODEVICE, mIfName);
|
Os.setsockoptIfreq(mSocket, SOL_SOCKET, SO_BINDTODEVICE, mInterface.name);
|
||||||
NetworkUtils.protectFromVpn(mSocket);
|
NetworkUtils.protectFromVpn(mSocket);
|
||||||
NetworkUtils.setupRaSocket(mSocket, mIfIndex);
|
NetworkUtils.setupRaSocket(mSocket, mInterface.index);
|
||||||
} catch (ErrnoException | IOException e) {
|
} catch (ErrnoException | IOException e) {
|
||||||
Log.e(TAG, "Failed to create RA daemon socket: " + e);
|
Log.e(TAG, "Failed to create RA daemon socket: " + e);
|
||||||
return false;
|
return false;
|
||||||
@@ -614,7 +611,7 @@ public class RouterAdvertisementDaemon {
|
|||||||
final InetAddress destip = dest.getAddress();
|
final InetAddress destip = dest.getAddress();
|
||||||
return (destip instanceof Inet6Address) &&
|
return (destip instanceof Inet6Address) &&
|
||||||
destip.isLinkLocalAddress() &&
|
destip.isLinkLocalAddress() &&
|
||||||
(((Inet6Address) destip).getScopeId() == mIfIndex);
|
(((Inet6Address) destip).getScopeId() == mInterface.index);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void maybeSendRA(InetSocketAddress dest) {
|
private void maybeSendRA(InetSocketAddress dest) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package android.net.util;
|
package android.net.util;
|
||||||
|
|
||||||
import android.net.dhcp.DhcpPacket;
|
import android.net.dhcp.DhcpPacket;
|
||||||
|
import android.net.MacAddress;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
@@ -45,21 +46,20 @@ public class ConnectivityPacketSummary {
|
|||||||
private final ByteBuffer mPacket;
|
private final ByteBuffer mPacket;
|
||||||
private final String mSummary;
|
private final String mSummary;
|
||||||
|
|
||||||
public static String summarize(byte[] hwaddr, byte[] buffer) {
|
public static String summarize(MacAddress hwaddr, byte[] buffer) {
|
||||||
return summarize(hwaddr, buffer, buffer.length);
|
return summarize(hwaddr, buffer, buffer.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Methods called herein perform some but by no means all error checking.
|
// Methods called herein perform some but by no means all error checking.
|
||||||
// They may throw runtime exceptions on malformed packets.
|
// They may throw runtime exceptions on malformed packets.
|
||||||
public static String summarize(byte[] hwaddr, byte[] buffer, int length) {
|
public static String summarize(MacAddress macAddr, byte[] buffer, int length) {
|
||||||
if ((hwaddr == null) || (hwaddr.length != ETHER_ADDR_LEN)) return null;
|
if ((macAddr == null) || (buffer == null)) return null;
|
||||||
if (buffer == null) return null;
|
|
||||||
length = Math.min(length, buffer.length);
|
length = Math.min(length, buffer.length);
|
||||||
return (new ConnectivityPacketSummary(hwaddr, buffer, length)).toString();
|
return (new ConnectivityPacketSummary(macAddr, buffer, length)).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConnectivityPacketSummary(byte[] hwaddr, byte[] buffer, int length) {
|
private ConnectivityPacketSummary(MacAddress macAddr, byte[] buffer, int length) {
|
||||||
mHwAddr = hwaddr;
|
mHwAddr = macAddr.toByteArray();
|
||||||
mBytes = buffer;
|
mBytes = buffer;
|
||||||
mLength = Math.min(length, mBytes.length);
|
mLength = Math.min(length, mBytes.length);
|
||||||
mPacket = ByteBuffer.wrap(mBytes, 0, mLength);
|
mPacket = ByteBuffer.wrap(mBytes, 0, mLength);
|
||||||
|
|||||||
94
services/net/java/android/net/util/InterfaceParams.java
Normal file
94
services/net/java/android/net/util/InterfaceParams.java
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 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.net.MacAddress.ALL_ZEROS_ADDRESS;
|
||||||
|
import static android.net.util.NetworkConstants.ETHER_MTU;
|
||||||
|
import static android.net.util.NetworkConstants.IPV6_MIN_MTU;
|
||||||
|
import static com.android.internal.util.Preconditions.checkArgument;
|
||||||
|
|
||||||
|
import android.net.MacAddress;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import java.net.NetworkInterface;
|
||||||
|
import java.net.SocketException;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulate the interface parameters common to IpClient/IpServer components.
|
||||||
|
*
|
||||||
|
* Basically all java.net.NetworkInterface methods throw Exceptions. IpClient
|
||||||
|
* and IpServer (sub)components need most or all of this information at some
|
||||||
|
* point during their lifecycles, so pass only this simplified object around
|
||||||
|
* which can be created once when IpClient/IpServer are told to start.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public class InterfaceParams {
|
||||||
|
public final String name;
|
||||||
|
public final int index;
|
||||||
|
public final MacAddress macAddr;
|
||||||
|
public final int defaultMtu;
|
||||||
|
|
||||||
|
public static InterfaceParams getByName(String name) {
|
||||||
|
final NetworkInterface netif = getNetworkInterfaceByName(name);
|
||||||
|
if (netif == null) return null;
|
||||||
|
|
||||||
|
// Not all interfaces have MAC addresses, e.g. rmnet_data0.
|
||||||
|
final MacAddress macAddr = getMacAddress(netif);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new InterfaceParams(name, netif.getIndex(), macAddr, netif.getMTU());
|
||||||
|
} catch (IllegalArgumentException|SocketException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public InterfaceParams(String name, int index, MacAddress macAddr) {
|
||||||
|
this(name, index, macAddr, ETHER_MTU);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InterfaceParams(String name, int index, MacAddress macAddr, int defaultMtu) {
|
||||||
|
checkArgument((!TextUtils.isEmpty(name)), "impossible interface name");
|
||||||
|
checkArgument((index > 0), "invalid interface index");
|
||||||
|
this.name = name;
|
||||||
|
this.index = index;
|
||||||
|
this.macAddr = (macAddr != null) ? macAddr : ALL_ZEROS_ADDRESS;
|
||||||
|
this.defaultMtu = (defaultMtu > IPV6_MIN_MTU) ? defaultMtu : IPV6_MIN_MTU;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("%s/%d/%s/%d", name, index, macAddr, defaultMtu);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static NetworkInterface getNetworkInterfaceByName(String name) {
|
||||||
|
try {
|
||||||
|
return NetworkInterface.getByName(name);
|
||||||
|
} catch (NullPointerException|SocketException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MacAddress getMacAddress(NetworkInterface netif) {
|
||||||
|
try {
|
||||||
|
return MacAddress.fromBytes(netif.getHardwareAddress());
|
||||||
|
} catch (IllegalArgumentException|NullPointerException|SocketException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -35,6 +35,7 @@ import android.net.apf.ApfGenerator.Register;
|
|||||||
import android.net.ip.IpManager;
|
import android.net.ip.IpManager;
|
||||||
import android.net.metrics.IpConnectivityLog;
|
import android.net.metrics.IpConnectivityLog;
|
||||||
import android.net.metrics.RaEvent;
|
import android.net.metrics.RaEvent;
|
||||||
|
import android.net.util.InterfaceParams;
|
||||||
import android.os.ConditionVariable;
|
import android.os.ConditionVariable;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
@@ -62,7 +63,6 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.NetworkInterface;
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
@@ -635,7 +635,7 @@ public class ApfTest {
|
|||||||
|
|
||||||
public TestApfFilter(ApfConfiguration config, IpManager.Callback ipManagerCallback,
|
public TestApfFilter(ApfConfiguration config, IpManager.Callback ipManagerCallback,
|
||||||
IpConnectivityLog log) throws Exception {
|
IpConnectivityLog log) throws Exception {
|
||||||
super(config, NetworkInterface.getByName("lo"), ipManagerCallback, log);
|
super(config, InterfaceParams.getByName("lo"), ipManagerCallback, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pretend an RA packet has been received and show it to ApfFilter.
|
// Pretend an RA packet has been received and show it to ApfFilter.
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import static org.junit.Assert.fail;
|
|||||||
import static org.mockito.Mockito.anyString;
|
import static org.mockito.Mockito.anyString;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.net.util.InterfaceParams;
|
||||||
import android.net.util.SharedLog;
|
import android.net.util.SharedLog;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
@@ -54,8 +55,8 @@ public class IpReachabilityMonitorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
IpReachabilityMonitor makeMonitor() {
|
IpReachabilityMonitor makeMonitor() {
|
||||||
return new IpReachabilityMonitor(
|
final InterfaceParams ifParams = new InterfaceParams("fake0", 1, null);
|
||||||
"fake0", 1, mHandler, mLog, mCallback, null, mDependencies);
|
return new IpReachabilityMonitor(ifParams, mHandler, mLog, mCallback, null, mDependencies);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import static android.net.util.NetworkConstants.*;
|
|||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import android.net.MacAddress;
|
||||||
import android.support.test.runner.AndroidJUnit4;
|
import android.support.test.runner.AndroidJUnit4;
|
||||||
import android.support.test.filters.SmallTest;
|
import android.support.test.filters.SmallTest;
|
||||||
|
|
||||||
@@ -36,9 +37,7 @@ import libcore.util.HexEncoding;
|
|||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
@SmallTest
|
@SmallTest
|
||||||
public class ConnectivityPacketSummaryTest {
|
public class ConnectivityPacketSummaryTest {
|
||||||
private static final byte[] MYHWADDR = {
|
private static final MacAddress MYHWADDR = MacAddress.fromString("80:7a:bf:6f:48:f3");
|
||||||
asByte(0x80), asByte(0x7a), asByte(0xbf), asByte(0x6f), asByte(0x48), asByte(0xf3)
|
|
||||||
};
|
|
||||||
|
|
||||||
private String getSummary(String hexBytes) {
|
private String getSummary(String hexBytes) {
|
||||||
hexBytes = hexBytes.replaceAll("\\s+", "");
|
hexBytes = hexBytes.replaceAll("\\s+", "");
|
||||||
|
|||||||
53
tests/net/java/android/net/util/InterfaceParamsTest.java
Normal file
53
tests/net/java/android/net/util/InterfaceParamsTest.java
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 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 org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import android.support.test.filters.SmallTest;
|
||||||
|
import android.support.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
@SmallTest
|
||||||
|
public class InterfaceParamsTest {
|
||||||
|
@Test
|
||||||
|
public void testNullInterfaceReturnsNull() {
|
||||||
|
assertNull(InterfaceParams.getByName(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNonExistentInterfaceReturnsNull() {
|
||||||
|
assertNull(InterfaceParams.getByName("doesnotexist0"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLoopback() {
|
||||||
|
final InterfaceParams ifParams = InterfaceParams.getByName("lo");
|
||||||
|
assertNotNull(ifParams);
|
||||||
|
assertEquals("lo", ifParams.name);
|
||||||
|
assertTrue(ifParams.index > 0);
|
||||||
|
assertNotNull(ifParams.macAddr);
|
||||||
|
assertTrue(ifParams.defaultMtu >= NetworkConstants.ETHER_MTU);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user