Merge "Refactor to InterfaceParams utility class"

This commit is contained in:
Treehugger Robot
2018-01-11 02:52:00 +00:00
committed by Gerrit Code Review
14 changed files with 275 additions and 169 deletions

View File

@@ -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) {

View File

@@ -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() {

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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;
} }

View File

@@ -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;
}
} }

View File

@@ -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));
} }
} }

View File

@@ -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) {

View File

@@ -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);

View 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;
}
}
}

View File

@@ -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.

View File

@@ -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

View File

@@ -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+", "");

View 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);
}
}