Merge "Refactor to InterfaceParams utility class" am: 6a91687bcd

am: fe83298cd5

Change-Id: Icb708a5ea7c3b41cb9d23885018b088c65ee427b
This commit is contained in:
Erik Kline
2018-01-11 04:02:15 +00:00
committed by android-build-merger
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.RouterAdvertisementDaemon;
import android.net.ip.RouterAdvertisementDaemon.RaParams;
import android.net.util.InterfaceParams;
import android.net.util.NetdService;
import android.net.util.SharedLog;
import android.os.INetworkManagementService;
@@ -48,7 +49,6 @@ import com.android.internal.util.StateMachine;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
@@ -120,8 +120,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
private int mLastError;
private int mServingMode;
private String mMyUpstreamIfaceName; // may change over time
private NetworkInterface mNetworkInterface;
private byte[] mHwAddr;
private InterfaceParams mInterfaceParams;
// TODO: De-duplicate this with mLinkProperties above. Currently, these link
// properties are those selected by the IPv6TetheringCoordinator and relayed
// to us. By comparison, mLinkProperties contains the addresses and directly
@@ -247,31 +246,16 @@ public class TetherInterfaceStateMachine extends StateMachine {
}
private boolean startIPv6() {
// TODO: Refactor for testability (perhaps passing an android.system.Os
// instance and calling getifaddrs() directly).
try {
mNetworkInterface = NetworkInterface.getByName(mIfaceName);
} catch (SocketException e) {
mLog.e("Error looking up NetworkInterfaces: " + e);
stopIPv6();
return false;
}
if (mNetworkInterface == null) {
mLog.e("Failed to find NetworkInterface");
// TODO: Refactor for better testability. This is one of the things
// that prohibits unittesting IPv6 tethering setup.
mInterfaceParams = InterfaceParams.getByName(mIfaceName);
if (mInterfaceParams == null) {
mLog.e("Failed to find InterfaceParams");
stopIPv6();
return false;
}
try {
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);
mRaDaemon = new RouterAdvertisementDaemon(mInterfaceParams);
if (!mRaDaemon.start()) {
stopIPv6();
return false;
@@ -281,8 +265,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
}
private void stopIPv6() {
mNetworkInterface = null;
mHwAddr = null;
mInterfaceParams = null;
setRaParams(null);
if (mRaDaemon != null) {

View File

@@ -38,6 +38,7 @@ import android.net.metrics.ApfProgramEvent;
import android.net.metrics.ApfStats;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.RaEvent;
import android.net.util.InterfaceParams;
import android.system.ErrnoException;
import android.system.Os;
import android.system.PacketSocketAddress;
@@ -56,7 +57,6 @@ import java.lang.Thread;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
@@ -247,7 +247,7 @@ public class ApfFilter {
private final ApfCapabilities mApfCapabilities;
private final IpClient.Callback mIpClientCallback;
private final NetworkInterface mNetworkInterface;
private final InterfaceParams mInterfaceParams;
private final IpConnectivityLog mMetricsLog;
@VisibleForTesting
@@ -269,11 +269,11 @@ public class ApfFilter {
private int mIPv4PrefixLength;
@VisibleForTesting
ApfFilter(ApfConfiguration config, NetworkInterface networkInterface,
ApfFilter(ApfConfiguration config, InterfaceParams ifParams,
IpClient.Callback ipClientCallback, IpConnectivityLog log) {
mApfCapabilities = config.apfCapabilities;
mIpClientCallback = ipClientCallback;
mNetworkInterface = networkInterface;
mInterfaceParams = ifParams;
mMulticastFilter = config.multicastFilter;
mDrop802_3Frames = config.ieee802_3Filter;
@@ -287,7 +287,7 @@ public class ApfFilter {
}
private void log(String s) {
Log.d(TAG, "(" + mNetworkInterface.getName() + "): " + s);
Log.d(TAG, "(" + mInterfaceParams.name + "): " + s);
}
@GuardedBy("this")
@@ -332,14 +332,14 @@ public class ApfFilter {
void maybeStartFilter() {
FileDescriptor socket;
try {
mHardwareAddress = mNetworkInterface.getHardwareAddress();
mHardwareAddress = mInterfaceParams.macAddr.toByteArray();
synchronized(this) {
// Install basic filters
installNewProgramLocked();
}
socket = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IPV6);
PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IPV6,
mNetworkInterface.getIndex());
PacketSocketAddress addr = new PacketSocketAddress(
(short) ETH_P_IPV6, mInterfaceParams.index);
Os.bind(socket, addr);
NetworkUtils.attachRaFilter(socket, mApfCapabilities.apfPacketFormat);
} catch(SocketException|ErrnoException e) {
@@ -1168,10 +1168,10 @@ public class ApfFilter {
* filtering using APF programs.
*/
public static ApfFilter maybeCreate(ApfConfiguration config,
NetworkInterface networkInterface, IpClient.Callback ipClientCallback) {
if (config == null) return null;
InterfaceParams ifParams, IpClient.Callback ipClientCallback) {
if (config == null || ifParams == null) return null;
ApfCapabilities apfCapabilities = config.apfCapabilities;
if (apfCapabilities == null || networkInterface == null) return null;
if (apfCapabilities == null) return null;
if (apfCapabilities.apfVersionSupported == 0) return null;
if (apfCapabilities.maximumApfProgramSize < 512) {
Log.e(TAG, "Unacceptably small APF limit: " + apfCapabilities.maximumApfProgramSize);
@@ -1186,7 +1186,7 @@ public class ApfFilter {
Log.e(TAG, "Unsupported APF version: " + apfCapabilities.apfVersionSupported);
return null;
}
return new ApfFilter(config, networkInterface, ipClientCallback, new IpConnectivityLog());
return new ApfFilter(config, ifParams, ipClientCallback, new IpConnectivityLog());
}
public synchronized void shutdown() {

View File

@@ -34,6 +34,7 @@ import android.net.TrafficStats;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.DhcpClientEvent;
import android.net.metrics.DhcpErrorEvent;
import android.net.util.InterfaceParams;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -50,7 +51,6 @@ import java.io.FileDescriptor;
import java.io.IOException;
import java.lang.Thread;
import java.net.Inet4Address;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.util.Arrays;
@@ -187,7 +187,8 @@ public class DhcpClient extends StateMachine {
private final String mIfaceName;
private boolean mRegisteredForPreDhcpNotification;
private NetworkInterface mIface;
private InterfaceParams mIface;
// TODO: MacAddress-ify more of this class hierarchy.
private byte[] mHwAddr;
private PacketSocketAddress mInterfaceBroadcastAddr;
private int mTransactionId;
@@ -221,6 +222,7 @@ public class DhcpClient extends StateMachine {
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) {
super(TAG);
@@ -262,23 +264,23 @@ public class DhcpClient extends StateMachine {
}
public static DhcpClient makeDhcpClient(
Context context, StateMachine controller, String intf) {
DhcpClient client = new DhcpClient(context, controller, intf);
Context context, StateMachine controller, InterfaceParams ifParams) {
DhcpClient client = new DhcpClient(context, controller, ifParams.name);
client.mIface = ifParams;
client.start();
return client;
}
private boolean initInterface() {
try {
mIface = NetworkInterface.getByName(mIfaceName);
mHwAddr = mIface.getHardwareAddress();
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);
if (mIface == null) mIface = InterfaceParams.getByName(mIfaceName);
if (mIface == null) {
Log.e(TAG, "Can't determine InterfaceParams for " + mIfaceName);
return false;
}
mHwAddr = mIface.macAddr.toByteArray();
mInterfaceBroadcastAddr = new PacketSocketAddress(mIface.index, DhcpPacket.ETHER_BROADCAST);
return true;
}
private void startNewTransaction() {
@@ -293,7 +295,7 @@ public class DhcpClient extends StateMachine {
private boolean initPacketSocket() {
try {
mPacketSock = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IP);
PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IP, mIface.getIndex());
PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IP, mIface.index);
Os.bind(mPacketSock, addr);
NetworkUtils.attachDhcpFilter(mPacketSock);
} catch(SocketException|ErrnoException e) {

View File

@@ -21,6 +21,7 @@ import static android.system.OsConstants.*;
import android.net.NetworkUtils;
import android.net.util.PacketReader;
import android.net.util.ConnectivityPacketSummary;
import android.net.util.InterfaceParams;
import android.os.Handler;
import android.system.ErrnoException;
import android.system.Os;
@@ -35,7 +36,6 @@ import libcore.util.HexEncoding;
import java.io.FileDescriptor;
import java.io.InterruptedIOException;
import java.io.IOException;
import java.net.NetworkInterface;
import java.net.SocketException;
@@ -69,24 +69,12 @@ public class ConnectivityPacketTracker {
private boolean mRunning;
private String mDisplayName;
public ConnectivityPacketTracker(Handler h, NetworkInterface netif, LocalLog log) {
final String ifname;
final int ifindex;
final byte[] hwaddr;
final int mtu;
public ConnectivityPacketTracker(Handler h, InterfaceParams ifParams, LocalLog log) {
if (ifParams == null) throw new IllegalArgumentException("null InterfaceParams");
try {
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;
mTag = TAG + "." + ifParams.name;
mLog = log;
mPacketListener = new PacketListener(h, ifindex, hwaddr, mtu);
mPacketListener = new PacketListener(h, ifParams);
}
public void start(String displayName) {
@@ -102,13 +90,11 @@ public class ConnectivityPacketTracker {
}
private final class PacketListener extends PacketReader {
private final int mIfIndex;
private final byte mHwAddr[];
private final InterfaceParams mInterface;
PacketListener(Handler h, int ifindex, byte[] hwaddr, int mtu) {
super(h, mtu);
mIfIndex = ifindex;
mHwAddr = hwaddr;
PacketListener(Handler h, InterfaceParams ifParams) {
super(h, ifParams.defaultMtu);
mInterface = ifParams;
}
@Override
@@ -117,7 +103,7 @@ public class ConnectivityPacketTracker {
try {
s = Os.socket(AF_PACKET, SOCK_RAW, 0);
NetworkUtils.attachControlPacketFilter(s, ARPHRD_ETHER);
Os.bind(s, new PacketSocketAddress((short) ETH_P_ALL, mIfIndex));
Os.bind(s, new PacketSocketAddress((short) ETH_P_ALL, mInterface.index));
} catch (ErrnoException | IOException e) {
logError("Failed to create packet tracking socket: ", e);
closeFd(s);
@@ -129,7 +115,7 @@ public class ConnectivityPacketTracker {
@Override
protected void handlePacket(byte[] recvbuf, int length) {
final String summary = ConnectivityPacketSummary.summarize(
mHwAddr, recvbuf, length);
mInterface.macAddr, recvbuf, length);
if (summary == null) return;
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.metrics.IpConnectivityLog;
import android.net.metrics.IpManagerEvent;
import android.net.util.InterfaceParams;
import android.net.util.MultinetworkPolicyTracker;
import android.net.util.NetdService;
import android.net.util.NetworkConstants;
@@ -63,7 +64,6 @@ import java.io.PrintWriter;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Collection;
@@ -556,7 +556,7 @@ public class IpClient extends StateMachine {
private final IpConnectivityLog mMetricsLog = new IpConnectivityLog();
private final InterfaceController mInterfaceCtrl;
private NetworkInterface mNetworkInterface;
private InterfaceParams mInterfaceParams;
/**
* Non-final member variables accessed only from within our StateMachine.
@@ -722,7 +722,12 @@ public class IpClient extends StateMachine {
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);
sendMessage(CMD_START, new ProvisioningConfiguration(req));
@@ -858,7 +863,7 @@ public class IpClient extends StateMachine {
protected String getLogRecString(Message msg) {
final String logLine = String.format(
"%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);
final String richerLogLine = getWhatToString(msg.what) + " " + logLine;
@@ -889,15 +894,6 @@ public class IpClient extends StateMachine {
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
// 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
@@ -1218,7 +1214,7 @@ public class IpClient extends StateMachine {
}
} else {
// Start DHCPv4.
mDhcpClient = DhcpClient.makeDhcpClient(mContext, IpClient.this, mInterfaceName);
mDhcpClient = DhcpClient.makeDhcpClient(mContext, IpClient.this, mInterfaceParams);
mDhcpClient.registerForPreDhcpNotification();
mDhcpClient.sendMessage(DhcpClient.CMD_START_DHCP);
}
@@ -1245,7 +1241,7 @@ public class IpClient extends StateMachine {
try {
mIpReachabilityMonitor = new IpReachabilityMonitor(
mContext,
mInterfaceName,
mInterfaceParams,
getHandler(),
mLog,
new IpReachabilityMonitor.Callback() {
@@ -1447,7 +1443,7 @@ public class IpClient extends StateMachine {
mContext.getResources().getBoolean(R.bool.config_apfDrop802_3Frames);
apfConfig.ethTypeBlackList =
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
// rest of this IP configuration startup.
if (mApfFilter == null) {
@@ -1515,7 +1511,7 @@ public class IpClient extends StateMachine {
private ConnectivityPacketTracker createPacketTracker() {
try {
return new ConnectivityPacketTracker(
getHandler(), mNetworkInterface, mConnectivityPacketLog);
getHandler(), mInterfaceParams, mConnectivityPacketLog);
} catch (IllegalArgumentException e) {
return null;
}

View File

@@ -16,7 +16,11 @@
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.NetlinkMessage;
import android.net.netlink.NetlinkSocket;
@@ -92,37 +96,35 @@ public class IpNeighborMonitor extends PacketReader {
final int ifindex;
final InetAddress ip;
final short nudState;
final byte[] linkLayerAddr;
final MacAddress macAddr;
public NeighborEvent(long elapsedMs, short msgType, int ifindex, InetAddress ip,
short nudState, byte[] linkLayerAddr) {
short nudState, MacAddress macAddr) {
this.elapsedMs = elapsedMs;
this.msgType = msgType;
this.ifindex = ifindex;
this.ip = ip;
this.nudState = nudState;
this.linkLayerAddr = linkLayerAddr;
this.macAddr = macAddr;
}
boolean isConnected() {
return (msgType != NetlinkConstants.RTM_DELNEIGH) &&
StructNdMsg.isNudStateConnected(nudState);
return (msgType != RTM_DELNEIGH) && StructNdMsg.isNudStateConnected(nudState);
}
boolean isValid() {
return (msgType != NetlinkConstants.RTM_DELNEIGH) &&
StructNdMsg.isNudStateValid(nudState);
return (msgType != RTM_DELNEIGH) && StructNdMsg.isNudStateValid(nudState);
}
@Override
public String toString() {
final StringJoiner j = new StringJoiner(",", "NeighborEvent{", "}");
return j.add("@" + elapsedMs)
.add(NetlinkConstants.stringForNlMsgType(msgType))
.add(stringForNlMsgType(msgType))
.add("if=" + ifindex)
.add(ip.getHostAddress())
.add(StructNdMsg.stringForNudState(nudState))
.add("[" + NetlinkConstants.hexify(linkLayerAddr) + "]")
.add("[" + macAddr + "]")
.toString();
}
}
@@ -183,7 +185,7 @@ public class IpNeighborMonitor extends PacketReader {
final NetlinkMessage nlMsg = NetlinkMessage.parse(byteBuffer);
if (nlMsg == null || nlMsg.getHeader() == null) {
byteBuffer.position(position);
mLog.e("unparsable netlink msg: " + NetlinkConstants.hexify(byteBuffer));
mLog.e("unparsable netlink msg: " + hexify(byteBuffer));
break;
}
@@ -217,12 +219,13 @@ public class IpNeighborMonitor extends PacketReader {
final int ifindex = ndMsg.ndm_ifindex;
final InetAddress destination = neighMsg.getDestination();
final short nudState =
(msgType == NetlinkConstants.RTM_DELNEIGH)
(msgType == RTM_DELNEIGH)
? StructNdMsg.NUD_NONE
: ndMsg.ndm_state;
final NeighborEvent event = new NeighborEvent(
whenMs, msgType, ifindex, destination, nudState, neighMsg.getLinkLayerAddress());
whenMs, msgType, ifindex, destination, nudState,
getMacAddress(neighMsg.getLinkLayerAddress()));
if (VDBG) {
Log.d(TAG, neighMsg.toString());
@@ -233,4 +236,16 @@ public class IpNeighborMonitor extends PacketReader {
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.IpReachabilityEvent;
import android.net.netlink.StructNdMsg;
import android.net.util.InterfaceParams;
import android.net.util.MultinetworkPolicyTracker;
import android.net.util.SharedLog;
import android.os.Handler;
@@ -46,9 +47,7 @@ import java.io.PrintWriter;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
@@ -168,8 +167,7 @@ public class IpReachabilityMonitor {
}
}
private final String mInterfaceName;
private final int mInterfaceIndex;
private final InterfaceParams mInterfaceParams;
private final IpNeighborMonitor mIpNeighborMonitor;
private final SharedLog mLog;
private final Callback mCallback;
@@ -182,30 +180,25 @@ public class IpReachabilityMonitor {
private volatile long mLastProbeTimeMs;
public IpReachabilityMonitor(
Context context, String ifName, 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,
Context context, InterfaceParams ifParams, Handler h, SharedLog log, Callback callback,
MultinetworkPolicyTracker tracker) {
this(ifName, getInterfaceIndex(ifName), h, log, callback, tracker,
Dependencies.makeDefault(context, ifName));
this(ifParams, h, log, callback, tracker, Dependencies.makeDefault(context, ifParams.name));
}
@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) {
mInterfaceName = ifName;
if (ifParams == null) throw new IllegalArgumentException("null InterfaceParams");
mInterfaceParams = ifParams;
mLog = log.forSubComponent(TAG);
mCallback = callback;
mMultinetworkPolicyTracker = tracker;
mInterfaceIndex = ifIndex;
mDependencies = dependencies;
mIpNeighborMonitor = new IpNeighborMonitor(h, mLog,
(NeighborEvent event) -> {
if (mInterfaceIndex != event.ifindex) return;
if (mInterfaceParams.index != event.ifindex) return;
if (!mNeighborWatchList.containsKey(event.ip)) return;
final NeighborEvent prev = mNeighborWatchList.put(event.ip, event);
@@ -241,7 +234,7 @@ public class IpReachabilityMonitor {
private String describeWatchList(String sep) {
final StringBuilder sb = new StringBuilder();
sb.append("iface{" + mInterfaceName + "/" + mInterfaceIndex + "}," + sep);
sb.append("iface{" + mInterfaceParams + "}," + sep);
sb.append("ntable=[" + sep);
String delimiter = "";
for (Map.Entry<InetAddress, NeighborEvent> entry : mNeighborWatchList.entrySet()) {
@@ -262,10 +255,10 @@ public class IpReachabilityMonitor {
}
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.
Log.wtf(TAG, "requested LinkProperties interface '" + lp.getInterfaceName() +
"' does not match: " + mInterfaceName);
"' does not match: " + mInterfaceParams.name);
return;
}
@@ -353,10 +346,10 @@ public class IpReachabilityMonitor {
mDependencies.acquireWakeLock(getProbeWakeLockDuration());
}
for (InetAddress target : ipProbeList) {
final int rval = IpNeighborMonitor.startKernelNeighborProbe(mInterfaceIndex, target);
for (InetAddress ip : ipProbeList) {
final int rval = IpNeighborMonitor.startKernelNeighborProbe(mInterfaceParams.index, ip);
mLog.log(String.format("put neighbor %s into NUD_PROBE state (rval=%d)",
target.getHostAddress(), rval));
ip.getHostAddress(), rval));
logEvent(IpReachabilityEvent.PROBE, rval);
}
mLastProbeTimeMs = SystemClock.elapsedRealtime();
@@ -378,22 +371,9 @@ public class IpReachabilityMonitor {
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) {
int eventType = probeType | (errorCode & 0xff);
mMetricsLog.log(mInterfaceName, new IpReachabilityEvent(eventType));
mMetricsLog.log(mInterfaceParams.name, new IpReachabilityEvent(eventType));
}
private void logNudFailed(ProvisioningChange delta) {
@@ -401,6 +381,6 @@ public class IpReachabilityMonitor {
boolean isFromProbe = (duration < getProbeWakeLockDuration());
boolean isProvisioningLost = (delta == ProvisioningChange.LOST_PROVISIONING);
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.NetworkUtils;
import android.net.TrafficStats;
import android.net.util.InterfaceParams;
import android.system.ErrnoException;
import android.system.Os;
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
};
private final String mIfName;
private final int mIfIndex;
private final byte[] mHwAddr;
private final InterfaceParams mInterface;
private final InetSocketAddress mAllNodes;
// 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) {
mIfName = ifname;
mIfIndex = ifindex;
mHwAddr = hwaddr;
mAllNodes = new InetSocketAddress(getAllNodesForScopeId(mIfIndex), 0);
public RouterAdvertisementDaemon(InterfaceParams ifParams) {
mInterface = ifParams;
mAllNodes = new InetSocketAddress(getAllNodesForScopeId(mInterface.index), 0);
mDeprecatedInfoTracker = new DeprecatedInfoTracker();
}
@@ -279,7 +276,7 @@ public class RouterAdvertisementDaemon {
try {
putHeader(ra, mRaParams != null && mRaParams.hasDefaultRoute);
putSlla(ra, mHwAddr);
putSlla(ra, mInterface.macAddr.toByteArray());
mRaLength = ra.position();
// https://tools.ietf.org/html/rfc5175#section-4 says:
@@ -579,9 +576,9 @@ public class RouterAdvertisementDaemon {
// Setting SNDTIMEO is purely for defensive purposes.
Os.setsockoptTimeval(
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.setupRaSocket(mSocket, mIfIndex);
NetworkUtils.setupRaSocket(mSocket, mInterface.index);
} catch (ErrnoException | IOException e) {
Log.e(TAG, "Failed to create RA daemon socket: " + e);
return false;
@@ -614,7 +611,7 @@ public class RouterAdvertisementDaemon {
final InetAddress destip = dest.getAddress();
return (destip instanceof Inet6Address) &&
destip.isLinkLocalAddress() &&
(((Inet6Address) destip).getScopeId() == mIfIndex);
(((Inet6Address) destip).getScopeId() == mInterface.index);
}
private void maybeSendRA(InetSocketAddress dest) {

View File

@@ -17,6 +17,7 @@
package android.net.util;
import android.net.dhcp.DhcpPacket;
import android.net.MacAddress;
import java.net.InetAddress;
import java.net.UnknownHostException;
@@ -45,21 +46,20 @@ public class ConnectivityPacketSummary {
private final ByteBuffer mPacket;
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);
}
// Methods called herein perform some but by no means all error checking.
// They may throw runtime exceptions on malformed packets.
public static String summarize(byte[] hwaddr, byte[] buffer, int length) {
if ((hwaddr == null) || (hwaddr.length != ETHER_ADDR_LEN)) return null;
if (buffer == null) return null;
public static String summarize(MacAddress macAddr, byte[] buffer, int length) {
if ((macAddr == null) || (buffer == null)) return null;
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) {
mHwAddr = hwaddr;
private ConnectivityPacketSummary(MacAddress macAddr, byte[] buffer, int length) {
mHwAddr = macAddr.toByteArray();
mBytes = buffer;
mLength = Math.min(length, mBytes.length);
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.metrics.IpConnectivityLog;
import android.net.metrics.RaEvent;
import android.net.util.InterfaceParams;
import android.os.ConditionVariable;
import android.os.Parcelable;
import android.os.SystemClock;
@@ -62,7 +63,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.Random;
@@ -635,7 +635,7 @@ public class ApfTest {
public TestApfFilter(ApfConfiguration config, IpManager.Callback ipManagerCallback,
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.

View File

@@ -21,6 +21,7 @@ import static org.junit.Assert.fail;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.when;
import android.net.util.InterfaceParams;
import android.net.util.SharedLog;
import android.os.Handler;
import android.os.Looper;
@@ -54,8 +55,8 @@ public class IpReachabilityMonitorTest {
}
IpReachabilityMonitor makeMonitor() {
return new IpReachabilityMonitor(
"fake0", 1, mHandler, mLog, mCallback, null, mDependencies);
final InterfaceParams ifParams = new InterfaceParams("fake0", 1, null);
return new IpReachabilityMonitor(ifParams, mHandler, mLog, mCallback, null, mDependencies);
}
@Test

View File

@@ -20,6 +20,7 @@ import static android.net.util.NetworkConstants.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import android.net.MacAddress;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.filters.SmallTest;
@@ -36,9 +37,7 @@ import libcore.util.HexEncoding;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class ConnectivityPacketSummaryTest {
private static final byte[] MYHWADDR = {
asByte(0x80), asByte(0x7a), asByte(0xbf), asByte(0x6f), asByte(0x48), asByte(0xf3)
};
private static final MacAddress MYHWADDR = MacAddress.fromString("80:7a:bf:6f:48:f3");
private String getSummary(String hexBytes) {
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);
}
}