diff options
Diffstat (limited to 'src/android/net/ip/IpClient.java')
-rw-r--r-- | src/android/net/ip/IpClient.java | 142 |
1 files changed, 135 insertions, 7 deletions
diff --git a/src/android/net/ip/IpClient.java b/src/android/net/ip/IpClient.java index 669dbfd..8e95ab5 100644 --- a/src/android/net/ip/IpClient.java +++ b/src/android/net/ip/IpClient.java @@ -27,6 +27,7 @@ import android.net.ConnectivityManager; import android.net.DhcpResults; import android.net.INetd; import android.net.IpPrefix; +import android.net.Layer2PacketParcelable; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.NattKeepalivePacketDataParcelable; @@ -38,6 +39,7 @@ import android.net.TcpKeepalivePacketDataParcelable; import android.net.apf.ApfCapabilities; import android.net.apf.ApfFilter; import android.net.dhcp.DhcpClient; +import android.net.dhcp.DhcpClient.Configuration; import android.net.metrics.IpConnectivityLog; import android.net.metrics.IpManagerEvent; import android.net.shared.InitialConfiguration; @@ -76,6 +78,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.net.InetAddress; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Set; @@ -178,6 +181,10 @@ public class IpClient extends StateMachine { mLog.e(PREFIX + msg, e); } + /** + * Callback called prior to DHCP discovery/renewal only if the pre DHCP action + * is enabled. + */ public void onPreDhcpAction() { log("onPreDhcpAction()"); try { @@ -187,6 +194,10 @@ public class IpClient extends StateMachine { } } + /** + * Callback called after DHCP discovery/renewal only if the pre DHCP action + * is enabled. + */ public void onPostDhcpAction() { log("onPostDhcpAction()"); try { @@ -196,6 +207,9 @@ public class IpClient extends StateMachine { } } + /** + * Callback called when new DHCP results are available. + */ public void onNewDhcpResults(DhcpResults dhcpResults) { log("onNewDhcpResults({" + dhcpResults + "})"); try { @@ -205,6 +219,9 @@ public class IpClient extends StateMachine { } } + /** + * Indicates that provisioning was successful. + */ public void onProvisioningSuccess(LinkProperties newLp) { log("onProvisioningSuccess({" + newLp + "})"); try { @@ -214,6 +231,9 @@ public class IpClient extends StateMachine { } } + /** + * Indicates that provisioning failed. + */ public void onProvisioningFailure(LinkProperties newLp) { log("onProvisioningFailure({" + newLp + "})"); try { @@ -223,6 +243,9 @@ public class IpClient extends StateMachine { } } + /** + * Invoked on LinkProperties changes. + */ public void onLinkPropertiesChange(LinkProperties newLp) { log("onLinkPropertiesChange({" + newLp + "})"); try { @@ -232,6 +255,10 @@ public class IpClient extends StateMachine { } } + /** + * Called when the internal IpReachabilityMonitor (if enabled) has detected the loss of + * required neighbors (e.g. on-link default gw or dns servers) due to NUD_FAILED. + */ public void onReachabilityLost(String logMsg) { log("onReachabilityLost(" + logMsg + ")"); try { @@ -241,6 +268,9 @@ public class IpClient extends StateMachine { } } + /** + * Called when the IpClient state machine terminates. + */ public void onQuit() { log("onQuit()"); try { @@ -250,6 +280,9 @@ public class IpClient extends StateMachine { } } + /** + * Called to indicate that a new APF program must be installed to filter incoming packets. + */ public void installPacketFilter(byte[] filter) { log("installPacketFilter(byte[" + filter.length + "])"); try { @@ -259,6 +292,10 @@ public class IpClient extends StateMachine { } } + /** + * Called to indicate that the APF Program & data buffer must be read asynchronously from + * the wifi driver. + */ public void startReadPacketFilter() { log("startReadPacketFilter()"); try { @@ -268,6 +305,10 @@ public class IpClient extends StateMachine { } } + /** + * If multicast filtering cannot be accomplished with APF, this function will be called to + * actuate multicast filtering using another means. + */ public void setFallbackMulticastFilter(boolean enabled) { log("setFallbackMulticastFilter(" + enabled + ")"); try { @@ -277,6 +318,10 @@ public class IpClient extends StateMachine { } } + /** + * Enabled/disable Neighbor Discover offload functionality. This is called, for example, + * whenever 464xlat is being started or stopped. + */ public void setNeighborDiscoveryOffload(boolean enable) { log("setNeighborDiscoveryOffload(" + enable + ")"); try { @@ -285,6 +330,18 @@ public class IpClient extends StateMachine { log("Failed to call setNeighborDiscoveryOffload", e); } } + + /** + * Invoked on starting preconnection process. + */ + public void onPreconnectionStart(List<Layer2PacketParcelable> packets) { + log("onPreconnectionStart(Layer2Packets[" + packets.size() + "])"); + try { + mCallback.onPreconnectionStart(packets); + } catch (RemoteException e) { + log("Failed to call onPreconnectionStart", e); + } + } } public static final String DUMP_ARG_CONFIRM = "confirm"; @@ -306,6 +363,7 @@ public class IpClient extends StateMachine { private static final int CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF = 13; private static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF = 14; private static final int CMD_UPDATE_L2KEY_GROUPHINT = 15; + protected static final int CMD_COMPLETE_PRECONNECTION = 16; // Internal commands to use instead of trying to call transitionTo() inside // a given State's enter() method. Calling transitionTo() from enter/exit @@ -345,6 +403,7 @@ public class IpClient extends StateMachine { private final State mClearingIpAddressesState = new ClearingIpAddressesState(); private final State mStartedState = new StartedState(); private final State mRunningState = new RunningState(); + private final State mPreconnectingState = new PreconnectingState(); private final String mTag; private final Context mContext; @@ -607,6 +666,11 @@ public class IpClient extends StateMachine { enforceNetworkStackCallingPermission(); IpClient.this.removeKeepalivePacketFilter(slot); } + @Override + public void notifyPreconnectionComplete(boolean success) { + enforceNetworkStackCallingPermission(); + IpClient.this.notifyPreconnectionComplete(success); + } @Override public int getInterfaceVersion() { @@ -622,6 +686,7 @@ public class IpClient extends StateMachine { // CHECKSTYLE:OFF IndentationCheck addState(mStoppedState); addState(mStartedState); + addState(mPreconnectingState, mStartedState); addState(mClearingIpAddressesState, mStartedState); addState(mRunningState, mStartedState); addState(mStoppingState); @@ -767,6 +832,15 @@ public class IpClient extends StateMachine { } /** + * Notify IpClient that preconnection is complete and that the link is ready for use. + * The success parameter indicates whether the packets passed in by onPreconnectionStart were + * successfully sent to the network or not. + */ + public void notifyPreconnectionComplete(boolean success) { + sendMessage(CMD_COMPLETE_PRECONNECTION, success ? 1 : 0); + } + + /** * Dump logs of this IpClient. */ public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { @@ -1229,11 +1303,10 @@ public class IpClient extends StateMachine { return false; } } else { - // Start DHCPv4. - mDhcpClient = DhcpClient.makeDhcpClient(mContext, IpClient.this, mInterfaceParams, - mDependencies.getDhcpClientDependencies(mIpMemoryStore)); - mDhcpClient.registerForPreDhcpNotification(); - mDhcpClient.sendMessage(DhcpClient.CMD_START_DHCP, mL2Key); + if (mDhcpClient != null) { + Log.wtf(mTag, "DhcpClient should never be non-null in startIPv4()"); + } + startDhcpClient(); } return true; @@ -1439,6 +1512,25 @@ public class IpClient extends StateMachine { } } + private boolean isUsingPreconnection() { + return mConfiguration.mEnablePreconnection && mConfiguration.mStaticIpConfig == null; + } + + private void startDhcpClient() { + // Start DHCPv4. + mDhcpClient = DhcpClient.makeDhcpClient(mContext, IpClient.this, mInterfaceParams, + mDependencies.getDhcpClientDependencies(mIpMemoryStore)); + + // If preconnection is enabled, there is no need to ask Wi-Fi to disable powersaving + // during DHCP, because the DHCP handshake will happen during association. In order to + // ensure that future renews still do the DHCP action (if configured), + // registerForPreDhcpNotification is called later when processing the CMD_*_PRECONNECTION + // messages. + if (!isUsingPreconnection()) mDhcpClient.registerForPreDhcpNotification(); + mDhcpClient.sendMessage(DhcpClient.CMD_START_DHCP, new Configuration(mL2Key, + isUsingPreconnection())); + } + class ClearingIpAddressesState extends State { @Override public void enter() { @@ -1456,7 +1548,7 @@ public class IpClient extends StateMachine { public boolean processMessage(Message msg) { switch (msg.what) { case CMD_ADDRESSES_CLEARED: - transitionTo(mRunningState); + transitionTo(isUsingPreconnection() ? mPreconnectingState : mRunningState); break; case EVENT_NETLINK_LINKPROPERTIES_CHANGED: @@ -1487,6 +1579,42 @@ public class IpClient extends StateMachine { } } + class PreconnectingState extends State { + @Override + public void enter() { + startDhcpClient(); + } + + @Override + public boolean processMessage(Message msg) { + switch (msg.what) { + case CMD_COMPLETE_PRECONNECTION: + boolean success = (msg.arg1 == 1); + mDhcpClient.registerForPreDhcpNotification(); + if (!success) { + mDhcpClient.sendMessage(DhcpClient.CMD_ABORT_PRECONNECTION); + } + // The link is ready for use. Advance to running state, start IPv6, etc. + transitionTo(mRunningState); + break; + + case DhcpClient.CMD_START_PRECONNECTION: + final Layer2PacketParcelable l2Packet = (Layer2PacketParcelable) msg.obj; + mCallback.onPreconnectionStart(Collections.singletonList(l2Packet)); + break; + + case CMD_STOP: + case EVENT_PROVISIONING_TIMEOUT: + // Fall through to StartedState. + return NOT_HANDLED; + + default: + deferMessage(msg); + } + return HANDLED; + } + } + class StartedState extends State { @Override public void enter() { @@ -1566,7 +1694,7 @@ public class IpClient extends StateMachine { return; } - if (mConfiguration.mEnableIPv4 && !startIPv4()) { + if (mConfiguration.mEnableIPv4 && !isUsingPreconnection() && !startIPv4()) { doImmediateProvisioningFailure(IpManagerEvent.ERROR_STARTING_IPV4); enqueueJumpToStoppingState(); return; |