Nat464Xlatpublic class Nat464Xlat extends com.android.server.net.BaseNetworkObserver
Fields Summary |
---|
private static final String | TAG | private static final String | CLAT_PREFIX | private final android.os.INetworkManagementService | mNMService | private final android.os.Handler | mHandler | private final NetworkAgentInfo | mNetwork | private String | mBaseIface | private String | mIface | private boolean | mIsRunning |
Methods Summary |
---|
private void | clear()Clears internal state. Must not be called by ConnectivityService.
mIface = null;
mBaseIface = null;
mIsRunning = false;
| public void | fixupLinkProperties(android.net.LinkProperties oldLp)Copies the stacked clat link in oldLp, if any, to the LinkProperties in mNetwork.
This is necessary because the LinkProperties in mNetwork come from the transport layer, which
has no idea that 464xlat is running on top of it.
if (mNetwork.clatd != null &&
mIsRunning &&
mNetwork.linkProperties != null &&
!mNetwork.linkProperties.getAllInterfaceNames().contains(mIface)) {
Slog.d(TAG, "clatd running, updating NAI for " + mIface);
for (LinkProperties stacked: oldLp.getStackedLinks()) {
if (mIface.equals(stacked.getInterfaceName())) {
mNetwork.linkProperties.addStackedLink(stacked);
break;
}
}
}
| private android.net.LinkAddress | getLinkAddress(java.lang.String iface)
try {
InterfaceConfiguration config = mNMService.getInterfaceConfig(iface);
return config.getLinkAddress();
} catch(RemoteException|IllegalStateException e) {
Slog.e(TAG, "Error getting link properties: " + e);
return null;
}
| public void | interfaceLinkStateChanged(java.lang.String iface, boolean up)
// Called by the InterfaceObserver on its own thread, so can race with stop().
if (isStarted() && up && mIface.equals(iface)) {
Slog.i(TAG, "interface " + iface + " is up, mIsRunning " + mIsRunning + "->true");
if (!mIsRunning) {
LinkAddress clatAddress = getLinkAddress(iface);
if (clatAddress == null) {
return;
}
mIsRunning = true;
maybeSetIpv6NdOffload(mBaseIface, false);
LinkProperties lp = new LinkProperties(mNetwork.linkProperties);
lp.addStackedLink(makeLinkProperties(clatAddress));
Slog.i(TAG, "Adding stacked link " + mIface + " on top of " + mBaseIface);
updateConnectivityService(lp);
}
}
| public void | interfaceRemoved(java.lang.String iface)
if (isStarted() && mIface.equals(iface)) {
Slog.i(TAG, "interface " + iface + " removed, mIsRunning " + mIsRunning + "->false");
if (mIsRunning) {
// The interface going away likely means clatd has crashed. Ask netd to stop it,
// because otherwise when we try to start it again on the same base interface netd
// will complain that it's already started.
//
// Note that this method can be called by the interface observer at the same time
// that ConnectivityService calls stop(). In this case, the second call to
// stopClatd() will just throw IllegalStateException, which we'll ignore.
try {
mNMService.unregisterObserver(this);
mNMService.stopClatd(mBaseIface);
} catch (RemoteException|IllegalStateException e) {
// Well, we tried.
}
maybeSetIpv6NdOffload(mBaseIface, true);
LinkProperties lp = new LinkProperties(mNetwork.linkProperties);
lp.removeStackedLink(mIface);
clear();
updateConnectivityService(lp);
}
}
| public boolean | isStarted()Determines whether clatd is started. Always true, except a) if start has not yet been called,
or b) if our interface was removed.
return mIface != null;
| private android.net.LinkProperties | makeLinkProperties(android.net.LinkAddress clatAddress)
LinkProperties stacked = new LinkProperties();
stacked.setInterfaceName(mIface);
// Although the clat interface is a point-to-point tunnel, we don't
// point the route directly at the interface because some apps don't
// understand routes without gateways (see, e.g., http://b/9597256
// http://b/9597516). Instead, set the next hop of the route to the
// clat IPv4 address itself (for those apps, it doesn't matter what
// the IP of the gateway is, only that there is one).
RouteInfo ipv4Default = new RouteInfo(
new LinkAddress(Inet4Address.ANY, 0),
clatAddress.getAddress(), mIface);
stacked.addRoute(ipv4Default);
stacked.addLinkAddress(clatAddress);
return stacked;
| private void | maybeSetIpv6NdOffload(java.lang.String iface, boolean on)
if (mNetwork.networkInfo.getType() != TYPE_WIFI) {
return;
}
try {
Slog.d(TAG, (on ? "En" : "Dis") + "abling ND offload on " + iface);
mNMService.setInterfaceIpv6NdOffload(iface, on);
} catch(RemoteException|IllegalStateException e) {
Slog.w(TAG, "Changing IPv6 ND offload on " + iface + "failed: " + e);
}
| public static boolean | requiresClat(NetworkAgentInfo nai)Determines whether a network requires clat.
final int netType = nai.networkInfo.getType();
final boolean connected = nai.networkInfo.isConnected();
final boolean hasIPv4Address =
(nai.linkProperties != null) ? nai.linkProperties.hasIPv4Address() : false;
// Only support clat on mobile and wifi for now, because these are the only IPv6-only
// networks we can connect to.
return connected && !hasIPv4Address && (netType == TYPE_MOBILE || netType == TYPE_WIFI);
| public void | start()Starts the clat daemon. Called by ConnectivityService on the handler thread.
if (isStarted()) {
Slog.e(TAG, "startClat: already started");
return;
}
if (mNetwork.linkProperties == null) {
Slog.e(TAG, "startClat: Can't start clat with null LinkProperties");
return;
}
try {
mNMService.registerObserver(this);
} catch(RemoteException e) {
Slog.e(TAG, "startClat: Can't register interface observer for clat on " + mNetwork);
return;
}
mBaseIface = mNetwork.linkProperties.getInterfaceName();
if (mBaseIface == null) {
Slog.e(TAG, "startClat: Can't start clat on null interface");
return;
}
mIface = CLAT_PREFIX + mBaseIface;
// From now on, isStarted() will return true.
Slog.i(TAG, "Starting clatd on " + mBaseIface);
try {
mNMService.startClatd(mBaseIface);
} catch(RemoteException|IllegalStateException e) {
Slog.e(TAG, "Error starting clatd: " + e);
}
| public void | stop()Stops the clat daemon. Called by ConnectivityService on the handler thread.
if (isStarted()) {
Slog.i(TAG, "Stopping clatd");
try {
mNMService.stopClatd(mBaseIface);
} catch(RemoteException|IllegalStateException e) {
Slog.e(TAG, "Error stopping clatd: " + e);
}
// When clatd stops and its interface is deleted, interfaceRemoved() will notify
// ConnectivityService and call clear().
} else {
Slog.e(TAG, "clatd: already stopped");
}
| private void | updateConnectivityService(android.net.LinkProperties lp)
Message msg = mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED, lp);
msg.replyTo = mNetwork.messenger;
Slog.i(TAG, "sending message to ConnectivityService: " + msg);
msg.sendToTarget();
|
|