Merge "Move IPv4 address setting to IpManager" into nyc-dev
This commit is contained in:
@@ -32,8 +32,6 @@ import android.net.LinkAddress;
|
|||||||
import android.net.NetworkUtils;
|
import android.net.NetworkUtils;
|
||||||
import android.net.metrics.DhcpClientEvent;
|
import android.net.metrics.DhcpClientEvent;
|
||||||
import android.net.metrics.DhcpErrorEvent;
|
import android.net.metrics.DhcpErrorEvent;
|
||||||
import android.os.IBinder;
|
|
||||||
import android.os.INetworkManagementService;
|
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ServiceManager;
|
import android.os.ServiceManager;
|
||||||
@@ -121,6 +119,13 @@ public class DhcpClient extends StateMachine {
|
|||||||
* after pre DHCP action is complete */
|
* after pre DHCP action is complete */
|
||||||
public static final int CMD_PRE_DHCP_ACTION_COMPLETE = PUBLIC_BASE + 7;
|
public static final int CMD_PRE_DHCP_ACTION_COMPLETE = PUBLIC_BASE + 7;
|
||||||
|
|
||||||
|
/* Command and event notification to/from IpManager requesting the setting
|
||||||
|
* (or clearing) of an IPv4 LinkAddress.
|
||||||
|
*/
|
||||||
|
public static final int CMD_CLEAR_LINKADDRESS = PUBLIC_BASE + 8;
|
||||||
|
public static final int CMD_CONFIGURE_LINKADDRESS = PUBLIC_BASE + 9;
|
||||||
|
public static final int EVENT_LINKADDRESS_CONFIGURED = PUBLIC_BASE + 10;
|
||||||
|
|
||||||
/* Message.arg1 arguments to CMD_POST_DHCP notification */
|
/* Message.arg1 arguments to CMD_POST_DHCP notification */
|
||||||
public static final int DHCP_SUCCESS = 1;
|
public static final int DHCP_SUCCESS = 1;
|
||||||
public static final int DHCP_FAILURE = 2;
|
public static final int DHCP_FAILURE = 2;
|
||||||
@@ -157,7 +162,6 @@ public class DhcpClient extends StateMachine {
|
|||||||
// System services / libraries we use.
|
// System services / libraries we use.
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final Random mRandom;
|
private final Random mRandom;
|
||||||
private final INetworkManagementService mNMService;
|
|
||||||
|
|
||||||
// Sockets.
|
// Sockets.
|
||||||
// - We use a packet socket to receive, because servers send us packets bound for IP addresses
|
// - We use a packet socket to receive, because servers send us packets bound for IP addresses
|
||||||
@@ -192,7 +196,8 @@ public class DhcpClient extends StateMachine {
|
|||||||
private State mDhcpInitState = new DhcpInitState();
|
private State mDhcpInitState = new DhcpInitState();
|
||||||
private State mDhcpSelectingState = new DhcpSelectingState();
|
private State mDhcpSelectingState = new DhcpSelectingState();
|
||||||
private State mDhcpRequestingState = new DhcpRequestingState();
|
private State mDhcpRequestingState = new DhcpRequestingState();
|
||||||
private State mDhcpHaveAddressState = new DhcpHaveAddressState();
|
private State mDhcpHaveLeaseState = new DhcpHaveLeaseState();
|
||||||
|
private State mConfiguringInterfaceState = new ConfiguringInterfaceState();
|
||||||
private State mDhcpBoundState = new DhcpBoundState();
|
private State mDhcpBoundState = new DhcpBoundState();
|
||||||
private State mDhcpRenewingState = new DhcpRenewingState();
|
private State mDhcpRenewingState = new DhcpRenewingState();
|
||||||
private State mDhcpRebindingState = new DhcpRebindingState();
|
private State mDhcpRebindingState = new DhcpRebindingState();
|
||||||
@@ -219,19 +224,17 @@ public class DhcpClient extends StateMachine {
|
|||||||
addState(mWaitBeforeStartState, mDhcpState);
|
addState(mWaitBeforeStartState, mDhcpState);
|
||||||
addState(mDhcpSelectingState, mDhcpState);
|
addState(mDhcpSelectingState, mDhcpState);
|
||||||
addState(mDhcpRequestingState, mDhcpState);
|
addState(mDhcpRequestingState, mDhcpState);
|
||||||
addState(mDhcpHaveAddressState, mDhcpState);
|
addState(mDhcpHaveLeaseState, mDhcpState);
|
||||||
addState(mDhcpBoundState, mDhcpHaveAddressState);
|
addState(mConfiguringInterfaceState, mDhcpHaveLeaseState);
|
||||||
addState(mWaitBeforeRenewalState, mDhcpHaveAddressState);
|
addState(mDhcpBoundState, mDhcpHaveLeaseState);
|
||||||
addState(mDhcpRenewingState, mDhcpHaveAddressState);
|
addState(mWaitBeforeRenewalState, mDhcpHaveLeaseState);
|
||||||
addState(mDhcpRebindingState, mDhcpHaveAddressState);
|
addState(mDhcpRenewingState, mDhcpHaveLeaseState);
|
||||||
|
addState(mDhcpRebindingState, mDhcpHaveLeaseState);
|
||||||
addState(mDhcpInitRebootState, mDhcpState);
|
addState(mDhcpInitRebootState, mDhcpState);
|
||||||
addState(mDhcpRebootingState, mDhcpState);
|
addState(mDhcpRebootingState, mDhcpState);
|
||||||
|
|
||||||
setInitialState(mStoppedState);
|
setInitialState(mStoppedState);
|
||||||
|
|
||||||
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
|
|
||||||
mNMService = INetworkManagementService.Stub.asInterface(b);
|
|
||||||
|
|
||||||
mRandom = new Random();
|
mRandom = new Random();
|
||||||
|
|
||||||
// Used to schedule packet retransmissions.
|
// Used to schedule packet retransmissions.
|
||||||
@@ -321,18 +324,6 @@ public class DhcpClient extends StateMachine {
|
|||||||
closeQuietly(mPacketSock);
|
closeQuietly(mPacketSock);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean setIpAddress(LinkAddress address) {
|
|
||||||
InterfaceConfiguration ifcg = new InterfaceConfiguration();
|
|
||||||
ifcg.setLinkAddress(address);
|
|
||||||
try {
|
|
||||||
mNMService.setInterfaceConfig(mIfaceName, ifcg);
|
|
||||||
} catch (RemoteException|IllegalStateException e) {
|
|
||||||
Log.e(TAG, "Error configuring IP address " + address + ": ", e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ReceiveThread extends Thread {
|
class ReceiveThread extends Thread {
|
||||||
|
|
||||||
private final byte[] mPacket = new byte[DhcpPacket.MAX_LENGTH];
|
private final byte[] mPacket = new byte[DhcpPacket.MAX_LENGTH];
|
||||||
@@ -382,7 +373,8 @@ public class DhcpClient extends StateMachine {
|
|||||||
Os.sendto(mPacketSock, buf.array(), 0, buf.limit(), 0, mInterfaceBroadcastAddr);
|
Os.sendto(mPacketSock, buf.array(), 0, buf.limit(), 0, mInterfaceBroadcastAddr);
|
||||||
} else {
|
} else {
|
||||||
// It's safe to call getpeername here, because we only send unicast packets if we
|
// It's safe to call getpeername here, because we only send unicast packets if we
|
||||||
// have an IP address, and we connect the UDP socket in DhcpHaveAddressState#enter.
|
// have an IP address, and we connect the UDP socket before
|
||||||
|
// ConfiguringInterfaceState#exit.
|
||||||
if (DBG) Log.d(TAG, "Unicasting " + description + " to " + Os.getpeername(mUdpSock));
|
if (DBG) Log.d(TAG, "Unicasting " + description + " to " + Os.getpeername(mUdpSock));
|
||||||
Os.write(mUdpSock, buf);
|
Os.write(mUdpSock, buf);
|
||||||
}
|
}
|
||||||
@@ -460,6 +452,7 @@ public class DhcpClient extends StateMachine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract class LoggingState extends State {
|
abstract class LoggingState extends State {
|
||||||
|
@Override
|
||||||
public void enter() {
|
public void enter() {
|
||||||
if (STATE_DBG) Log.d(TAG, "Entering state " + getName());
|
if (STATE_DBG) Log.d(TAG, "Entering state " + getName());
|
||||||
DhcpClientEvent.logStateEvent(mIfaceName, getName());
|
DhcpClientEvent.logStateEvent(mIfaceName, getName());
|
||||||
@@ -759,7 +752,7 @@ public class DhcpClient extends StateMachine {
|
|||||||
mOffer = null;
|
mOffer = null;
|
||||||
Log.d(TAG, "Confirmed lease: " + mDhcpLease);
|
Log.d(TAG, "Confirmed lease: " + mDhcpLease);
|
||||||
setDhcpLeaseExpiry(packet);
|
setDhcpLeaseExpiry(packet);
|
||||||
transitionTo(mDhcpBoundState);
|
transitionTo(mConfiguringInterfaceState);
|
||||||
}
|
}
|
||||||
} else if (packet instanceof DhcpNakPacket) {
|
} else if (packet instanceof DhcpNakPacket) {
|
||||||
// TODO: Wait a while before returning into INIT state.
|
// TODO: Wait a while before returning into INIT state.
|
||||||
@@ -776,24 +769,52 @@ public class DhcpClient extends StateMachine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DhcpHaveAddressState extends LoggingState {
|
class DhcpHaveLeaseState extends LoggingState {
|
||||||
@Override
|
@Override
|
||||||
public void enter() {
|
public void enter() {
|
||||||
super.enter();
|
super.enter();
|
||||||
if (!setIpAddress(mDhcpLease.ipAddress) ||
|
|
||||||
(mDhcpLease.serverAddress != null &&
|
|
||||||
!connectUdpSock((mDhcpLease.serverAddress)))) {
|
|
||||||
notifyFailure();
|
|
||||||
// There's likely no point in going into DhcpInitState here, we'll probably just
|
|
||||||
// repeat the transaction, get the same IP address as before, and fail.
|
|
||||||
transitionTo(mStoppedState);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exit() {
|
public void exit() {
|
||||||
if (DBG) Log.d(TAG, "Clearing IP address");
|
// Tell IpManager to clear the IPv4 address. There is no need to
|
||||||
setIpAddress(new LinkAddress("0.0.0.0/0"));
|
// wait for confirmation since any subsequent packets are sent from
|
||||||
|
// INADDR_ANY anyway (DISCOVER, REQUEST).
|
||||||
|
mController.sendMessage(CMD_CLEAR_LINKADDRESS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConfiguringInterfaceState extends LoggingState {
|
||||||
|
@Override
|
||||||
|
public void enter() {
|
||||||
|
super.enter();
|
||||||
|
mController.sendMessage(CMD_CONFIGURE_LINKADDRESS, mDhcpLease.ipAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean processMessage(Message message) {
|
||||||
|
super.processMessage(message);
|
||||||
|
switch (message.what) {
|
||||||
|
case EVENT_LINKADDRESS_CONFIGURED:
|
||||||
|
if (mDhcpLease.serverAddress != null &&
|
||||||
|
!connectUdpSock(mDhcpLease.serverAddress)) {
|
||||||
|
// There's likely no point in going into DhcpInitState here, we'll probably
|
||||||
|
// just repeat the transaction, get the same IP address as before, and fail.
|
||||||
|
//
|
||||||
|
// NOTE: It is observed that connectUdpSock() basically never fails, due to
|
||||||
|
// SO_BINDTODEVICE. Examining the local socket address shows it will happily
|
||||||
|
// return an IPv4 address from another interface, or even return "0.0.0.0".
|
||||||
|
//
|
||||||
|
// TODO: Consider deleting this check, following testing on several kernels.
|
||||||
|
notifyFailure();
|
||||||
|
transitionTo(mStoppedState);
|
||||||
|
} else {
|
||||||
|
transitionTo(mDhcpBoundState);
|
||||||
|
}
|
||||||
|
return HANDLED;
|
||||||
|
default:
|
||||||
|
return NOT_HANDLED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -803,8 +824,8 @@ public class DhcpClient extends StateMachine {
|
|||||||
super.enter();
|
super.enter();
|
||||||
mOneshotTimeoutAlarm.cancel();
|
mOneshotTimeoutAlarm.cancel();
|
||||||
notifySuccess();
|
notifySuccess();
|
||||||
// TODO: DhcpStateMachine only supported renewing at 50% of the lease time, and did not
|
// TODO: DhcpStateMachine only supported renewing at 50% of the lease time,
|
||||||
// support rebinding. Once the legacy DHCP client is gone, fix this.
|
// and did not support rebinding. Now that the legacy DHCP client is gone, fix this.
|
||||||
scheduleRenew();
|
scheduleRenew();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -770,6 +770,19 @@ public class IpManager extends StateMachine {
|
|||||||
return (delta != ProvisioningChange.LOST_PROVISIONING);
|
return (delta != ProvisioningChange.LOST_PROVISIONING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean setIPv4Address(LinkAddress address) {
|
||||||
|
final InterfaceConfiguration ifcg = new InterfaceConfiguration();
|
||||||
|
ifcg.setLinkAddress(address);
|
||||||
|
try {
|
||||||
|
mNwService.setInterfaceConfig(mInterfaceName, ifcg);
|
||||||
|
if (VDBG) Log.d(mTag, "IPv4 configuration succeeded");
|
||||||
|
} catch (IllegalStateException | RemoteException e) {
|
||||||
|
Log.e(mTag, "IPv4 configuration failed: ", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private void clearIPv4Address() {
|
private void clearIPv4Address() {
|
||||||
try {
|
try {
|
||||||
final InterfaceConfiguration ifcg = new InterfaceConfiguration();
|
final InterfaceConfiguration ifcg = new InterfaceConfiguration();
|
||||||
@@ -794,7 +807,6 @@ public class IpManager extends StateMachine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleIPv4Failure() {
|
private void handleIPv4Failure() {
|
||||||
// TODO: Figure out to de-dup this and the same code in DhcpClient.
|
|
||||||
clearIPv4Address();
|
clearIPv4Address();
|
||||||
mDhcpResults = null;
|
mDhcpResults = null;
|
||||||
final LinkProperties newLp = assembleLinkProperties();
|
final LinkProperties newLp = assembleLinkProperties();
|
||||||
@@ -944,7 +956,7 @@ public class IpManager extends StateMachine {
|
|||||||
// If we have a StaticIpConfiguration attempt to apply it and
|
// If we have a StaticIpConfiguration attempt to apply it and
|
||||||
// handle the result accordingly.
|
// handle the result accordingly.
|
||||||
if (mConfiguration.mStaticIpConfig != null) {
|
if (mConfiguration.mStaticIpConfig != null) {
|
||||||
if (applyStaticIpConfig()) {
|
if (setIPv4Address(mConfiguration.mStaticIpConfig.ipAddress)) {
|
||||||
handleIPv4Success(new DhcpResults(mConfiguration.mStaticIpConfig));
|
handleIPv4Success(new DhcpResults(mConfiguration.mStaticIpConfig));
|
||||||
} else {
|
} else {
|
||||||
if (VDBG) { Log.d(mTag, "onProvisioningFailure()"); }
|
if (VDBG) { Log.d(mTag, "onProvisioningFailure()"); }
|
||||||
@@ -1050,6 +1062,21 @@ public class IpManager extends StateMachine {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DhcpClient.CMD_CLEAR_LINKADDRESS:
|
||||||
|
clearIPv4Address();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DhcpClient.CMD_CONFIGURE_LINKADDRESS: {
|
||||||
|
final LinkAddress ipAddress = (LinkAddress) msg.obj;
|
||||||
|
if (setIPv4Address(ipAddress)) {
|
||||||
|
mDhcpClient.sendMessage(DhcpClient.EVENT_LINKADDRESS_CONFIGURED);
|
||||||
|
} else {
|
||||||
|
Log.e(mTag, "Failed to set IPv4 address!");
|
||||||
|
transitionTo(mStoppingState);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case DhcpClient.CMD_POST_DHCP_ACTION: {
|
case DhcpClient.CMD_POST_DHCP_ACTION: {
|
||||||
// Note that onPostDhcpAction() is likely to be
|
// Note that onPostDhcpAction() is likely to be
|
||||||
// asynchronous, and thus there is no guarantee that we
|
// asynchronous, and thus there is no guarantee that we
|
||||||
@@ -1082,20 +1109,5 @@ public class IpManager extends StateMachine {
|
|||||||
}
|
}
|
||||||
return HANDLED;
|
return HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean applyStaticIpConfig() {
|
|
||||||
final InterfaceConfiguration ifcg = new InterfaceConfiguration();
|
|
||||||
ifcg.setLinkAddress(mConfiguration.mStaticIpConfig.ipAddress);
|
|
||||||
ifcg.setInterfaceUp();
|
|
||||||
try {
|
|
||||||
mNwService.setInterfaceConfig(mInterfaceName, ifcg);
|
|
||||||
if (DBG) Log.d(mTag, "Static IP configuration succeeded");
|
|
||||||
} catch (IllegalStateException | RemoteException e) {
|
|
||||||
Log.e(mTag, "Static IP configuration failed: ", e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user